diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 7377ea3ffe353..3fb8a5f2d1b8e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -116,6 +116,7 @@ /x-pack/plugins/monitoring/ @elastic/infra-monitoring-ui /x-pack/test/functional/apps/monitoring @elastic/infra-monitoring-ui /x-pack/test/api_integration/apis/monitoring @elastic/infra-monitoring-ui +/x-pack/test/api_integration/apis/monitoring_collection @elastic/infra-monitoring-ui # Fleet /fleet_packages.json @elastic/fleet @@ -150,9 +151,6 @@ # Client Side Monitoring / Uptime (lives in APM directories but owned by Uptime) /x-pack/plugins/apm/public/application/uxApp.tsx @elastic/uptime /x-pack/plugins/apm/public/components/app/rum_dashboard @elastic/uptime -/x-pack/plugins/apm/server/lib/rum_client @elastic/uptime -/x-pack/plugins/apm/server/routes/rum_client.ts @elastic/uptime -/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts @elastic/uptime /x-pack/test/apm_api_integration/tests/csm/ @elastic/uptime ### END Observability Plugins @@ -268,6 +266,8 @@ /test/functional/services/common @elastic/kibana-qa /test/functional/services/lib @elastic/kibana-qa /test/functional/services/remote @elastic/kibana-qa +/test/visual_regression @elastic/kibana-qa +/x-pack/test/visual_regression @elastic/kibana-qa # Core /examples/hello_world/ @elastic/kibana-core @@ -275,6 +275,7 @@ /src/plugins/saved_objects_tagging_oss @elastic/kibana-core /config/kibana.yml @elastic/kibana-core /typings/ @elastic/kibana-core +/x-pack/plugins/global_search_providers @elastic/kibana-core /x-pack/plugins/banners/ @elastic/kibana-core /x-pack/plugins/features/ @elastic/kibana-core /x-pack/plugins/licensing/ @elastic/kibana-core @@ -333,6 +334,7 @@ /packages/kbn-handlebars/ @elastic/kibana-security /packages/core/http/core-http-server-internal/src/csp/ @elastic/kibana-security @elastic/kibana-core /src/plugins/interactive_setup/ @elastic/kibana-security +/src/plugins/telemetry/server/config/telemetry_labels.ts @elastic/kibana-security /test/interactive_setup_api_integration/ @elastic/kibana-security /test/interactive_setup_functional/ @elastic/kibana-security /test/plugin_functional/test_suites/core_plugins/rendering.ts @elastic/kibana-security diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index 6800aeea65b9d..efc03d8942b8d 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -17,7 +17,3 @@ - "x-pack/plugins/synthetics/**/*.*" - "x-pack/plugins/ux/**/*.*" - "x-pack/plugins/observability/public/components/shared/exploratory_view/**/*.*" - - "x-pack/plugins/apm/server/lib/rum_client/**/*.*" - - "x-pack/plugins/apm/server/lib/rum_client/*.*" - - "x-pack/plugins/apm/server/routes/rum_client.ts" - - "x-pack/plugins/apm/server/projections/rum_overview.ts" diff --git a/.i18nrc.json b/.i18nrc.json index 073a413fabf80..08f2ff151b4c2 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -9,8 +9,7 @@ "console": "src/plugins/console", "core": [ "src/core", - "packages/core/i18n/core-i18n-browser-internal", - "packages/core/fatal-errors/core-fatal-errors-browser-internal" + "packages/core" ], "customIntegrations": "src/plugins/custom_integrations", "dashboard": "src/plugins/dashboard", diff --git a/api-documenter.json b/api-documenter.json deleted file mode 100644 index a2303b939c8ec..0000000000000 --- a/api-documenter.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "newlineKind": "lf", - "outputTarget": "markdown" -} diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index b37fe3df21ad2..e8945cef729e1 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github summary: API docs for the actions plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] warning: 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. --- diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index d7284bf2ba87a..5022616c6831d 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github summary: API docs for the advancedSettings plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] warning: 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. --- diff --git a/api_docs/aiops.devdocs.json b/api_docs/aiops.devdocs.json index a9675003d2e1f..e351d2c17883e 100644 --- a/api_docs/aiops.devdocs.json +++ b/api_docs/aiops.devdocs.json @@ -10,17 +10,11 @@ "tags": [], "label": "ExplainLogRateSpikes", "description": [ - "\nLazy-wrapped ExplainLogRateSpikes React component" + "\nLazy-wrapped ExplainLogRateSpikesWrapper React component" ], "signature": [ "(props: React.PropsWithChildren<", - { - "pluginId": "aiops", - "scope": "public", - "docId": "kibAiopsPluginApi", - "section": "def-public.ExplainLogRateSpikesProps", - "text": "ExplainLogRateSpikesProps" - }, + "ExplainLogRateSpikesWrapperProps", ">) => JSX.Element" ], "path": "x-pack/plugins/aiops/public/shared_lazy_components.tsx", @@ -37,13 +31,7 @@ ], "signature": [ "React.PropsWithChildren<", - { - "pluginId": "aiops", - "scope": "public", - "docId": "kibAiopsPluginApi", - "section": "def-public.ExplainLogRateSpikesProps", - "text": "ExplainLogRateSpikesProps" - }, + "ExplainLogRateSpikesWrapperProps", ">" ], "path": "x-pack/plugins/aiops/public/shared_lazy_components.tsx", @@ -55,59 +43,7 @@ "initialIsOpen": false } ], - "interfaces": [ - { - "parentPluginId": "aiops", - "id": "def-public.ExplainLogRateSpikesProps", - "type": "Interface", - "tags": [], - "label": "ExplainLogRateSpikesProps", - "description": [ - "\nExplainLogRateSpikes props require a data view." - ], - "path": "x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes.tsx", - "deprecated": false, - "children": [ - { - "parentPluginId": "aiops", - "id": "def-public.ExplainLogRateSpikesProps.dataView", - "type": "Object", - "tags": [], - "label": "dataView", - "description": [ - "The data view to analyze." - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - } - ], - "path": "x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes.tsx", - "deprecated": false - }, - { - "parentPluginId": "aiops", - "id": "def-public.ExplainLogRateSpikesProps.windowParameters", - "type": "Object", - "tags": [], - "label": "windowParameters", - "description": [ - "Window parameters for the analysis" - ], - "signature": [ - "WindowParameters" - ], - "path": "x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes.tsx", - "deprecated": false - } - ], - "initialIsOpen": false - } - ], + "interfaces": [], "enums": [], "misc": [], "objects": [], diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 618ea5e1eb78d..785d17c4eab03 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github summary: API docs for the aiops plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 12 | 0 | 0 | 0 | +| 9 | 0 | 0 | 1 | ## Client @@ -28,9 +28,6 @@ Contact [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) for q ### Functions -### Interfaces - - ## Server ### Setup diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 7b86f41380cf8..17f5b697744b4 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github summary: API docs for the alerting plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] warning: 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. --- diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index 06c67d2dc2974..97812e861a663 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -772,7 +772,7 @@ "label": "APIEndpoint", "description": [], "signature": [ - "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/dynamic\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/ux/page-load-distribution\" | \"GET /internal/apm/ux/page-load-distribution/breakdown\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/backend\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/profiling/timeline\" | \"GET /internal/apm/services/{serviceName}/profiling/statistics\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/sorted_and_filtered_services\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/backends/top_backends\" | \"GET /internal/apm/backends/upstream_services\" | \"GET /internal/apm/backends/metadata\" | \"GET /internal/apm/backends/charts/latency\" | \"GET /internal/apm/backends/charts/throughput\" | \"GET /internal/apm/backends/charts/error_rate\" | \"GET /internal/apm/backends/operations\" | \"GET /internal/apm/backends/charts/distribution\" | \"GET /internal/apm/backends/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"POST /internal/apm/correlations/field_stats/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\"" + "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/dynamic\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/backend\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/profiling/timeline\" | \"GET /internal/apm/services/{serviceName}/profiling/statistics\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/sorted_and_filtered_services\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/backends/top_backends\" | \"GET /internal/apm/backends/upstream_services\" | \"GET /internal/apm/backends/metadata\" | \"GET /internal/apm/backends/charts/latency\" | \"GET /internal/apm/backends/charts/throughput\" | \"GET /internal/apm/backends/charts/error_rate\" | \"GET /internal/apm/backends/operations\" | \"GET /internal/apm/backends/charts/distribution\" | \"GET /internal/apm/backends/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"POST /internal/apm/correlations/field_stats/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\"" ], "path": "x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts", "deprecated": false, @@ -4740,90 +4740,6 @@ "ServiceAnomalyStats", " | undefined; label: string | undefined; id?: string | undefined; parent?: string | undefined; position?: cytoscape.Position | undefined; } | { 'span.destination.service.resource': string; 'span.type': string; 'span.subtype': string; label: string | undefined; id?: string | undefined; parent?: string | undefined; position?: cytoscape.Position | undefined; } | { id: string; source: string | undefined; target: string | undefined; label: string | undefined; bidirectional?: boolean | undefined; isInverseEdge?: boolean | undefined; } | undefined)[]; }; } | { data: { id: string; source: string; target: string; }; })[]; }, ", "APMRouteCreateOptions", - ">; \"GET /internal/apm/ux/page-load-distribution/breakdown\": ", - "ServerRoute", - "<\"GET /internal/apm/ux/page-load-distribution/breakdown\", ", - "TypeC", - "<{ query: ", - "IntersectionC", - "<[", - "IntersectionC", - "<[", - "TypeC", - "<{ uiFilters: ", - "StringC", - "; }>, ", - "TypeC", - "<{ start: ", - "Type", - "; end: ", - "Type", - "; }>, ", - "PartialC", - "<{ urlQuery: ", - "StringC", - "; percentile: ", - "StringC", - "; }>]>, ", - "PartialC", - "<{ minPercentile: ", - "StringC", - "; maxPercentile: ", - "StringC", - "; }>, ", - "TypeC", - "<{ breakdown: ", - "StringC", - "; }>]>; }>, ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, - ", { pageLoadDistBreakdown: { name: string; data: { x: number; y: number; }[]; }[] | undefined; }, ", - "APMRouteCreateOptions", - ">; \"GET /internal/apm/ux/page-load-distribution\": ", - "ServerRoute", - "<\"GET /internal/apm/ux/page-load-distribution\", ", - "TypeC", - "<{ query: ", - "IntersectionC", - "<[", - "IntersectionC", - "<[", - "TypeC", - "<{ uiFilters: ", - "StringC", - "; }>, ", - "TypeC", - "<{ start: ", - "Type", - "; end: ", - "Type", - "; }>, ", - "PartialC", - "<{ urlQuery: ", - "StringC", - "; percentile: ", - "StringC", - "; }>]>, ", - "PartialC", - "<{ minPercentile: ", - "StringC", - "; maxPercentile: ", - "StringC", - "; }>]>; }>, ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, - ", { pageLoadDistribution: { pageLoadDistribution: { x: number; y: number; }[]; percentiles: Record | undefined; minDuration: number; maxDuration: number; } | null; }, ", - "APMRouteCreateOptions", ">; \"GET /internal/apm/observability_overview/has_data\": ", "ServerRoute", "<\"GET /internal/apm/observability_overview/has_data\", undefined, ", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 1e52586d92225..8730e14f8beb5 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github summary: API docs for the apm plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] warning: 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. --- diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 60a50ae742061..d8f2405083928 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github summary: API docs for the banners plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] warning: 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. --- diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index d11bfb0ab67a5..463a6033a3fa2 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github summary: API docs for the bfetch plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] warning: 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. --- diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index e647d472c91f9..986d62a680b9b 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github summary: API docs for the canvas plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] warning: 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. --- diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 2aa643e48d15b..51472be3d0720 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github summary: API docs for the cases plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] warning: 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. --- diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 9671ccbe8af2f..2adb2fc9eccbf 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github summary: API docs for the charts plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] warning: 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. --- diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 01ec58337accf..2afff6557bcab 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github summary: API docs for the cloud plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] warning: 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. --- diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 21e18763c07cc..c26f1d8683db9 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github summary: API docs for the cloudSecurityPosture plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] warning: 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. --- diff --git a/api_docs/console.mdx b/api_docs/console.mdx index bf2db61245112..094305df01eee 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github summary: API docs for the console plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] warning: 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. --- diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index fc1869da56022..988a33e511c60 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github summary: API docs for the controls plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] warning: 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. --- diff --git a/api_docs/core.devdocs.json b/api_docs/core.devdocs.json index 04ccf7434c847..d2573ca167afc 100644 --- a/api_docs/core.devdocs.json +++ b/api_docs/core.devdocs.json @@ -62,13 +62,7 @@ "label": "uiSettings", "description": [], "signature": [ - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - } + "IUiSettingsClient" ], "path": "src/core/public/notifications/toasts/toasts_api.tsx", "deprecated": false @@ -1318,13 +1312,7 @@ "{@link IUiSettingsClient}" ], "signature": [ - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - } + "IUiSettingsClient" ], "path": "src/core/public/index.ts", "deprecated": false @@ -1610,13 +1598,7 @@ "{@link IUiSettingsClient}" ], "signature": [ - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - } + "IUiSettingsClient" ], "path": "src/core/public/index.ts", "deprecated": false @@ -1646,13 +1628,7 @@ "{@link DeprecationsServiceStart}" ], "signature": [ - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.DeprecationsServiceStart", - "text": "DeprecationsServiceStart" - } + "DeprecationsServiceStart" ], "path": "src/core/public/index.ts", "deprecated": false @@ -1726,7 +1702,7 @@ "description": [ "\nDeprecationsService provides methods to fetch domain deprecation details from\nthe Kibana server.\n" ], - "path": "src/core/public/deprecations/deprecations_service.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "children": [ { @@ -1743,7 +1719,7 @@ "DomainDeprecationDetails", "[]>" ], - "path": "src/core/public/deprecations/deprecations_service.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "children": [], "returnComment": [] @@ -1762,7 +1738,7 @@ "DomainDeprecationDetails", "[]>" ], - "path": "src/core/public/deprecations/deprecations_service.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "children": [ { @@ -1775,7 +1751,7 @@ "signature": [ "string" ], - "path": "src/core/public/deprecations/deprecations_service.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -1796,7 +1772,7 @@ "DomainDeprecationDetails", ") => boolean" ], - "path": "src/core/public/deprecations/deprecations_service.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "children": [ { @@ -1809,7 +1785,7 @@ "signature": [ "DomainDeprecationDetails" ], - "path": "src/core/public/deprecations/deprecations_service.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -1829,16 +1805,10 @@ "(details: ", "DomainDeprecationDetails", ") => Promise<", - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.ResolveDeprecationResponse", - "text": "ResolveDeprecationResponse" - }, + "ResolveDeprecationResponse", ">" ], - "path": "src/core/public/deprecations/deprecations_service.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "children": [ { @@ -1851,7 +1821,7 @@ "signature": [ "DomainDeprecationDetails" ], - "path": "src/core/public/deprecations/deprecations_service.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -4481,7 +4451,7 @@ "description": [ "\nClient-side client that provides access to the advanced settings stored in elasticsearch.\nThe settings provide control over the behavior of the Kibana application.\nFor example, a user can specify how to display numeric or date fields.\nUsers can adjust the settings via Management UI.\n{@link IUiSettingsClient}\n" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4496,7 +4466,7 @@ "signature": [ "(key: string, defaultOverride?: T | undefined) => T" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4509,7 +4479,7 @@ "signature": [ "string" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true }, @@ -4523,7 +4493,7 @@ "signature": [ "T | undefined" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": false } @@ -4544,7 +4514,7 @@ "Observable", "" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4557,7 +4527,7 @@ "signature": [ "string" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true }, @@ -4571,7 +4541,7 @@ "signature": [ "T | undefined" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": false } @@ -4594,7 +4564,7 @@ "UserProvidedValues", ">>" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [], "returnComment": [] @@ -4611,7 +4581,7 @@ "signature": [ "(key: string, value: any) => Promise" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4624,7 +4594,7 @@ "signature": [ "string" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true }, @@ -4638,7 +4608,7 @@ "signature": [ "any" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -4657,7 +4627,7 @@ "signature": [ "(key: string) => Promise" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4670,7 +4640,7 @@ "signature": [ "string" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -4689,7 +4659,7 @@ "signature": [ "(key: string) => boolean" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4702,7 +4672,7 @@ "signature": [ "string" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -4721,7 +4691,7 @@ "signature": [ "(key: string) => boolean" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4734,7 +4704,7 @@ "signature": [ "string" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -4753,7 +4723,7 @@ "signature": [ "(key: string) => boolean" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4766,7 +4736,7 @@ "signature": [ "string" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -4785,7 +4755,7 @@ "signature": [ "(key: string) => boolean" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -4798,7 +4768,7 @@ "signature": [ "string" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "isRequired": true } @@ -4819,7 +4789,7 @@ "Observable", "<{ key: string; newValue: T; oldValue: T; }>" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [], "returnComment": [] @@ -4838,7 +4808,7 @@ "Observable", "" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [], "returnComment": [] @@ -8795,7 +8765,7 @@ "UiSettingsParams", "" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "children": [ { @@ -8810,7 +8780,7 @@ "signature": [ "string | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8825,7 +8795,7 @@ "signature": [ "T | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8840,7 +8810,7 @@ "signature": [ "string | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8855,7 +8825,7 @@ "signature": [ "string[] | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8870,7 +8840,7 @@ "signature": [ "string[] | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8885,7 +8855,7 @@ "signature": [ "Record | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8900,7 +8870,7 @@ "signature": [ "boolean | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8915,7 +8885,7 @@ "signature": [ "boolean | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8930,7 +8900,7 @@ "signature": [ "boolean | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8946,7 +8916,7 @@ "UiSettingsType", " | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8962,7 +8932,7 @@ "DeprecationSettings", " | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8977,7 +8947,7 @@ "signature": [ "number | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -8991,7 +8961,7 @@ "Type", "" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -9008,7 +8978,7 @@ "signature": [ "{ type: string; name: string; } | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": true, "references": [ { @@ -9039,7 +9009,7 @@ "tags": [], "label": "UiSettingsState", "description": [], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false, "children": [ { @@ -9056,7 +9026,7 @@ "UserProvidedValues", "" ], - "path": "src/core/public/ui_settings/types.ts", + "path": "node_modules/@types/kbn__core-ui-settings-browser/index.d.ts", "deprecated": false } ], @@ -9075,7 +9045,7 @@ "UserProvidedValues", "" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "children": [ { @@ -9088,7 +9058,7 @@ "signature": [ "T | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -9101,7 +9071,7 @@ "signature": [ "boolean | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false } ], @@ -9180,6 +9150,21 @@ "deprecated": false, "initialIsOpen": false }, + { + "parentPluginId": "core", + "id": "def-public.DomainDeprecationDetails", + "type": "Type", + "tags": [], + "label": "DomainDeprecationDetails", + "description": [], + "signature": [ + "DeprecationsDetails", + " & { domainId: string; }" + ], + "path": "node_modules/@types/kbn__core-deprecations-common/index.d.ts", + "deprecated": false, + "initialIsOpen": false + }, { "parentPluginId": "core", "id": "def-public.EventType", @@ -9550,7 +9535,7 @@ "DeprecationSettings", " | undefined; }" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "initialIsOpen": false }, @@ -9560,11 +9545,13 @@ "type": "Type", "tags": [], "label": "ResolveDeprecationResponse", - "description": [], + "description": [ + "\nResponse from correctiveActions.api call from automatically resolving the deprecation" + ], "signature": [ "{ status: \"ok\"; } | { status: \"fail\"; reason: string; }" ], - "path": "src/core/public/deprecations/deprecations_client.ts", + "path": "node_modules/@types/kbn__core-deprecations-browser/index.d.ts", "deprecated": false, "initialIsOpen": false }, @@ -10118,7 +10105,7 @@ "signature": [ "\"string\" | \"number\" | \"boolean\" | \"undefined\" | \"color\" | \"image\" | \"json\" | \"markdown\" | \"select\" | \"array\"" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "initialIsOpen": false }, @@ -10161,6 +10148,92 @@ }, "server": { "classes": [ + { + "parentPluginId": "core", + "id": "def-server.CspConfig", + "type": "Class", + "tags": [], + "label": "CspConfig", + "description": [ + "\nCSP configuration for use in Kibana." + ], + "signature": [ + "CspConfig", + " implements ", + "ICspConfig" + ], + "path": "node_modules/@types/kbn__core-http-server-internal/index.d.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "core", + "id": "def-server.CspConfig.private", + "type": "Any", + "tags": [], + "label": "#private", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/kbn__core-http-server-internal/index.d.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.DEFAULT", + "type": "Object", + "tags": [], + "label": "DEFAULT", + "description": [], + "signature": [ + "CspConfig" + ], + "path": "node_modules/@types/kbn__core-http-server-internal/index.d.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.strict", + "type": "boolean", + "tags": [], + "label": "strict", + "description": [], + "path": "node_modules/@types/kbn__core-http-server-internal/index.d.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.warnLegacyBrowsers", + "type": "boolean", + "tags": [], + "label": "warnLegacyBrowsers", + "description": [], + "path": "node_modules/@types/kbn__core-http-server-internal/index.d.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.disableEmbedding", + "type": "boolean", + "tags": [], + "label": "disableEmbedding", + "description": [], + "path": "node_modules/@types/kbn__core-http-server-internal/index.d.ts", + "deprecated": false + }, + { + "parentPluginId": "core", + "id": "def-server.CspConfig.header", + "type": "string", + "tags": [], + "label": "header", + "description": [], + "path": "node_modules/@types/kbn__core-http-server-internal/index.d.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "core", "id": "def-server.ElasticsearchConfig", @@ -11519,120 +11592,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "core", - "id": "def-server.BaseDeprecationDetails", - "type": "Interface", - "tags": [], - "label": "BaseDeprecationDetails", - "description": [ - "\nBase properties shared by all types of deprecations\n" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.BaseDeprecationDetails.title", - "type": "string", - "tags": [], - "label": "title", - "description": [ - "\nThe title of the deprecation.\nCheck the README for writing deprecations in `src/core/server/deprecations/README.mdx`" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.BaseDeprecationDetails.message", - "type": "string", - "tags": [], - "label": "message", - "description": [ - "\nThe description message to be displayed for the deprecation.\nCheck the README for writing deprecations in `src/core/server/deprecations/README.mdx`" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.BaseDeprecationDetails.level", - "type": "CompoundType", - "tags": [], - "label": "level", - "description": [ - "\nlevels:\n- warning: will not break deployment upon upgrade\n- critical: needs to be addressed before upgrade.\n- fetch_error: Deprecations service failed to grab the deprecation details for the domain." - ], - "signature": [ - "\"warning\" | \"critical\" | \"fetch_error\"" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.BaseDeprecationDetails.deprecationType", - "type": "CompoundType", - "tags": [], - "label": "deprecationType", - "description": [ - "\n(optional) Used to identify between different deprecation types.\nExample use case: in Upgrade Assistant, we may want to allow the user to sort by\ndeprecation type or show each type in a separate tab.\n\nFeel free to add new types if necessary.\nPredefined types are necessary to reduce having similar definitions with different keywords\nacross kibana deprecations." - ], - "signature": [ - "\"config\" | \"feature\" | undefined" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.BaseDeprecationDetails.documentationUrl", - "type": "string", - "tags": [], - "label": "documentationUrl", - "description": [ - "(optional) link to the documentation for more details on the deprecation." - ], - "signature": [ - "string | undefined" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.BaseDeprecationDetails.requireRestart", - "type": "CompoundType", - "tags": [], - "label": "requireRestart", - "description": [ - "(optional) specify the fix for this deprecation requires a full kibana restart." - ], - "signature": [ - "boolean | undefined" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.BaseDeprecationDetails.correctiveActions", - "type": "Object", - "tags": [], - "label": "correctiveActions", - "description": [ - "corrective action needed to fix this deprecation." - ], - "signature": [ - "{ api?: { path: string; method: \"POST\" | \"PUT\"; body?: { [key: string]: any; } | undefined; omitContextFromBody?: boolean | undefined; } | undefined; manualSteps: string[]; }" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "core", "id": "def-server.Capabilities", @@ -11950,59 +11909,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "core", - "id": "def-server.ConfigDeprecationDetails", - "type": "Interface", - "tags": [], - "label": "ConfigDeprecationDetails", - "description": [], - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.ConfigDeprecationDetails", - "text": "ConfigDeprecationDetails" - }, - " extends ", - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.BaseDeprecationDetails", - "text": "BaseDeprecationDetails" - } - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.ConfigDeprecationDetails.configPath", - "type": "string", - "tags": [], - "label": "configPath", - "description": [], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.ConfigDeprecationDetails.deprecationType", - "type": "string", - "tags": [], - "label": "deprecationType", - "description": [], - "signature": [ - "\"config\"" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "core", "id": "def-server.ConfigDeprecationFactory", @@ -13312,7 +13218,7 @@ "description": [ "\nUiSettings deprecation field options." ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "children": [ { @@ -13324,7 +13230,7 @@ "description": [ "Deprecation message" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -13336,7 +13242,7 @@ "description": [ "Key to documentation links" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false } ], @@ -14528,49 +14434,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "core", - "id": "def-server.FeatureDeprecationDetails", - "type": "Interface", - "tags": [], - "label": "FeatureDeprecationDetails", - "description": [], - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.FeatureDeprecationDetails", - "text": "FeatureDeprecationDetails" - }, - " extends ", - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.BaseDeprecationDetails", - "text": "BaseDeprecationDetails" - } - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.FeatureDeprecationDetails.deprecationType", - "type": "string", - "tags": [], - "label": "deprecationType", - "description": [], - "signature": [ - "\"feature\" | undefined" - ], - "path": "src/core/server/deprecations/types.ts", - "deprecated": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "core", "id": "def-server.GetDeprecationsContext", @@ -25796,13 +25659,7 @@ ") => ", "MaybePromise", "<", - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.DeprecationsDetails", - "text": "DeprecationsDetails" - }, + "DeprecationsDetails", "[]>" ], "path": "src/core/server/deprecations/types.ts", @@ -27346,7 +27203,7 @@ "UiSettingsParams", "" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "children": [ { @@ -27361,7 +27218,7 @@ "signature": [ "string | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27376,7 +27233,7 @@ "signature": [ "T | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27391,7 +27248,7 @@ "signature": [ "string | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27406,7 +27263,7 @@ "signature": [ "string[] | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27421,7 +27278,7 @@ "signature": [ "string[] | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27436,7 +27293,7 @@ "signature": [ "Record | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27451,7 +27308,7 @@ "signature": [ "boolean | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27466,7 +27323,7 @@ "signature": [ "boolean | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27481,7 +27338,7 @@ "signature": [ "boolean | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27497,7 +27354,7 @@ "UiSettingsType", " | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27513,7 +27370,7 @@ "DeprecationSettings", " | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27528,7 +27385,7 @@ "signature": [ "number | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27542,7 +27399,7 @@ "Type", "" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27559,7 +27416,7 @@ "signature": [ "{ type: string; name: string; } | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": true, "references": [ { @@ -27973,7 +27830,7 @@ "UserProvidedValues", "" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "children": [ { @@ -27986,7 +27843,7 @@ "signature": [ "T | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false }, { @@ -27999,7 +27856,7 @@ "signature": [ "boolean | undefined" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false } ], @@ -28565,23 +28422,11 @@ "label": "DeprecationsDetails", "description": [], "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.ConfigDeprecationDetails", - "text": "ConfigDeprecationDetails" - }, + "ConfigDeprecationDetails", " | ", - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.FeatureDeprecationDetails", - "text": "FeatureDeprecationDetails" - } + "FeatureDeprecationDetails" ], - "path": "src/core/server/deprecations/types.ts", + "path": "node_modules/@types/kbn__core-deprecations-common/index.d.ts", "deprecated": false, "initialIsOpen": false }, @@ -30480,6 +30325,33 @@ "deprecated": false, "initialIsOpen": false }, + { + "parentPluginId": "core", + "id": "def-server.kibanaResponseFactory", + "type": "CompoundType", + "tags": [], + "label": "kibanaResponseFactory", + "description": [], + "signature": [ + "KibanaSuccessResponseFactory", + " & ", + "KibanaRedirectionResponseFactory", + " & ", + "KibanaErrorResponseFactory", + " & { custom | Error | ", + "Stream", + " | Buffer | { message: string | Error; attributes?: ", + "ResponseErrorAttributes", + " | undefined; } | undefined>(options: ", + "CustomHttpResponseOptions", + "): ", + "IKibanaResponse", + "; }" + ], + "path": "node_modules/@types/kbn__core-http-router-server-internal/index.d.ts", + "deprecated": false, + "initialIsOpen": false + }, { "parentPluginId": "core", "id": "def-server.KibanaResponseFactory", @@ -31198,7 +31070,7 @@ "DeprecationSettings", " | undefined; }" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "initialIsOpen": false }, @@ -31461,9 +31333,9 @@ "\nThe set of common HTTP methods supported by Kibana routing." ], "signature": [ - "SafeRouteMethod", + "DestructiveRouteMethod", " | ", - "DestructiveRouteMethod" + "SafeRouteMethod" ], "path": "node_modules/@types/kbn__core-http-server/index.d.ts", "deprecated": false, @@ -31828,7 +31700,7 @@ "signature": [ "\"string\" | \"number\" | \"boolean\" | \"undefined\" | \"color\" | \"image\" | \"json\" | \"markdown\" | \"select\" | \"array\"" ], - "path": "src/core/types/ui_settings.ts", + "path": "node_modules/@types/kbn__core-ui-settings-common/index.d.ts", "deprecated": false, "initialIsOpen": false }, diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 1ca2a7bd7646b..56e16b3050365 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github summary: API docs for the core plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 2489 | 9 | 746 | 25 | +| 2472 | 5 | 705 | 17 | ## Client diff --git a/api_docs/core_application.mdx b/api_docs/core_application.mdx index 73e1cc4df37c8..88f4cd2db44dd 100644 --- a/api_docs/core_application.mdx +++ b/api_docs/core_application.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-application title: "core.application" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.application plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.application'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 2489 | 9 | 746 | 25 | +| 2472 | 5 | 705 | 17 | ## Client diff --git a/api_docs/core_chrome.mdx b/api_docs/core_chrome.mdx index 38935d4adbf2c..32a4cf35438f1 100644 --- a/api_docs/core_chrome.mdx +++ b/api_docs/core_chrome.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-chrome title: "core.chrome" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.chrome plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.chrome'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 2489 | 9 | 746 | 25 | +| 2472 | 5 | 705 | 17 | ## Client diff --git a/api_docs/core_http.devdocs.json b/api_docs/core_http.devdocs.json deleted file mode 100644 index 3aea850ad213e..0000000000000 --- a/api_docs/core_http.devdocs.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "id": "core.http", - "client": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "server": { - "classes": [ - { - "parentPluginId": "core", - "id": "def-server.CspConfig", - "type": "Class", - "tags": [], - "label": "CspConfig", - "description": [ - "\nCSP configuration for use in Kibana." - ], - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCoreHttpPluginApi", - "section": "def-server.CspConfig", - "text": "CspConfig" - }, - " implements ", - "ICspConfig" - ], - "path": "src/core/server/http/csp/csp_config.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.CspConfig.DEFAULT", - "type": "Object", - "tags": [], - "label": "DEFAULT", - "description": [], - "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCoreHttpPluginApi", - "section": "def-server.CspConfig", - "text": "CspConfig" - } - ], - "path": "src/core/server/http/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.directives", - "type": "Object", - "tags": [], - "label": "#directives", - "description": [], - "signature": [ - "CspDirectives" - ], - "path": "src/core/server/http/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.strict", - "type": "boolean", - "tags": [], - "label": "strict", - "description": [], - "path": "src/core/server/http/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.warnLegacyBrowsers", - "type": "boolean", - "tags": [], - "label": "warnLegacyBrowsers", - "description": [], - "path": "src/core/server/http/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.disableEmbedding", - "type": "boolean", - "tags": [], - "label": "disableEmbedding", - "description": [], - "path": "src/core/server/http/csp/csp_config.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.CspConfig.header", - "type": "string", - "tags": [], - "label": "header", - "description": [], - "path": "src/core/server/http/csp/csp_config.ts", - "deprecated": false - } - ], - "initialIsOpen": false - } - ], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [ - { - "parentPluginId": "core", - "id": "def-server.kibanaResponseFactory", - "type": "Object", - "tags": [], - "label": "kibanaResponseFactory", - "description": [], - "path": "src/core/server/http/router/response.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.kibanaResponseFactory.Unnamed", - "type": "Any", - "tags": [], - "label": "Unnamed", - "description": [], - "signature": [ - "any" - ], - "path": "src/core/server/http/router/response.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.kibanaResponseFactory.Unnamed", - "type": "Any", - "tags": [], - "label": "Unnamed", - "description": [], - "signature": [ - "any" - ], - "path": "src/core/server/http/router/response.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.kibanaResponseFactory.Unnamed", - "type": "Any", - "tags": [], - "label": "Unnamed", - "description": [], - "signature": [ - "any" - ], - "path": "src/core/server/http/router/response.ts", - "deprecated": false - }, - { - "parentPluginId": "core", - "id": "def-server.kibanaResponseFactory.custom", - "type": "Function", - "tags": [], - "label": "custom", - "description": [], - "signature": [ - " | Error | ", - "Stream", - " | Buffer | { message: string | Error; attributes?: ", - "ResponseErrorAttributes", - " | undefined; } | undefined>(options: ", - "CustomHttpResponseOptions", - ") => ", - "KibanaResponse", - "" - ], - "path": "src/core/server/http/router/response.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "core", - "id": "def-server.kibanaResponseFactory.custom.$1", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "signature": [ - "CustomHttpResponseOptions", - "" - ], - "path": "src/core/server/http/router/response.ts", - "deprecated": false, - "isRequired": true - } - ], - "returnComment": [] - } - ], - "initialIsOpen": false - } - ] - }, - "common": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - } -} \ No newline at end of file diff --git a/api_docs/core_http.mdx b/api_docs/core_http.mdx deleted file mode 100644 index 3dca29910f474..0000000000000 --- a/api_docs/core_http.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -id: kibCoreHttpPluginApi -slug: /kibana-dev-docs/api/core-http -title: "core.http" -image: https://source.unsplash.com/400x175/?github -summary: API docs for the core.http plugin -date: 2022-07-13 -tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.http'] -warning: 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. ---- -import coreHttpObj from './core_http.devdocs.json'; - - - -Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. - -**Code health stats** - -| Public API count | Any count | Items lacking comments | Missing exports | -|-------------------|-----------|------------------------|-----------------| -| 2489 | 9 | 746 | 25 | - -## Server - -### Objects - - -### Classes - - diff --git a/api_docs/core_saved_objects.mdx b/api_docs/core_saved_objects.mdx index ef05af39d188d..116e3a56e3e58 100644 --- a/api_docs/core_saved_objects.mdx +++ b/api_docs/core_saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/core-savedObjects title: "core.savedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the core.savedObjects plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core.savedObjects'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 2489 | 9 | 746 | 25 | +| 2472 | 5 | 705 | 17 | ## Client diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index ee0b3ef00b9be..3bd19babc28a7 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github summary: API docs for the customIntegrations plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] warning: 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. --- diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 17a5f089230cd..f3034074e4400 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github summary: API docs for the dashboard plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] warning: 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. --- diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index cb8a65c67c0e3..f45056cab1ace 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the dashboardEnhanced plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] warning: 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. --- diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index cc89249f62a1b..140ce8e70bb5c 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -645,7 +645,15 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "" + ">" ], "path": "src/plugins/data/common/search/aggs/agg_config.ts", "deprecated": false, @@ -6991,13 +6999,7 @@ "label": "uiSettings", "description": [], "signature": [ - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - } + "IUiSettingsClient" ], "path": "src/plugins/data/public/types.ts", "deprecated": false @@ -12955,7 +12957,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">) => void" ], @@ -12995,7 +12997,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">" ], @@ -13852,7 +13854,7 @@ "\nCreate a new data view instance." ], "signature": [ - "({ id, ...restOfSpec }: ", + "({ id, name, title, ...restOfSpec }: ", { "pluginId": "dataViews", "scope": "common", @@ -13878,7 +13880,7 @@ "id": "def-server.DataViewsService.create.$1", "type": "Object", "tags": [], - "label": "{ id, ...restOfSpec }", + "label": "{ id, name, title, ...restOfSpec }", "description": [], "signature": [ { @@ -19389,7 +19391,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">) => void" ], @@ -19429,7 +19431,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">" ], @@ -19517,7 +19519,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", { @@ -20993,7 +20995,7 @@ "\nCreate a new data view instance." ], "signature": [ - "({ id, ...restOfSpec }: ", + "({ id, name, title, ...restOfSpec }: ", { "pluginId": "dataViews", "scope": "common", @@ -21019,7 +21021,7 @@ "id": "def-common.DataViewsService.create.$1", "type": "Object", "tags": [], - "label": "{ id, ...restOfSpec }", + "label": "{ id, name, title, ...restOfSpec }", "description": [], "signature": [ { @@ -22619,7 +22621,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">> | undefined; runtimeFieldMap?: Record> | undefined; runtimeFieldMap?: Record | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", { diff --git a/api_docs/data.mdx b/api_docs/data.mdx index f6c01d22f9c87..61df290a1ec40 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github summary: API docs for the data plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] warning: 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. --- diff --git a/api_docs/data_query.devdocs.json b/api_docs/data_query.devdocs.json index a061d52a3ae43..bd9bfa16a841d 100644 --- a/api_docs/data_query.devdocs.json +++ b/api_docs/data_query.devdocs.json @@ -53,13 +53,7 @@ "label": "uiSettings", "description": [], "signature": [ - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - } + "IUiSettingsClient" ], "path": "src/plugins/data/public/query/filter_manager/filter_manager.ts", "deprecated": false, diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 50c49ba0251eb..8be2485775d9b 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github summary: API docs for the data.query plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] warning: 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. --- diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index a406c0bcb8d3f..65cfc70b670cd 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -1465,16 +1465,7 @@ "docId": "kibDataSearchPluginApi", "section": "def-server.ISearchSessionService", "text": "ISearchSessionService" - }, - "<", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.SearchSessionSavedObjectAttributes", - "text": "SearchSessionSavedObjectAttributes" - }, - ">" + } ], "path": "src/plugins/data/server/search/session/session_service.ts", "deprecated": false, @@ -2718,9 +2709,25 @@ "label": "saveSession", "description": [], "signature": [ - "(sessionId: string, attributes: Partial) => Promise<", + "(sessionId: string, attributes: Partial<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionSavedObjectAttributes", + "text": "SearchSessionSavedObjectAttributes" + }, + ">) => Promise<", "SavedObject", - " | undefined>" + "<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionSavedObjectAttributes", + "text": "SearchSessionSavedObjectAttributes" + }, + "> | undefined>" ], "path": "src/plugins/data/server/search/types.ts", "deprecated": false, @@ -2744,7 +2751,27 @@ "label": "attributes", "description": [], "signature": [ - "{ [P in keyof T]?: T[P] | undefined; }" + "{ sessionId?: string | undefined; name?: string | undefined; appId?: string | undefined; created?: string | undefined; touched?: string | undefined; expires?: string | undefined; completed?: string | null | undefined; status?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionStatus", + "text": "SearchSessionStatus" + }, + " | undefined; locatorId?: string | undefined; initialState?: ", + "SerializableRecord", + " | undefined; restoreState?: ", + "SerializableRecord", + " | undefined; idMapping?: Record | undefined; persisted?: boolean | undefined; realmType?: string | undefined; realmName?: string | undefined; username?: string | undefined; version?: string | undefined; }" ], "path": "src/plugins/data/server/search/session/types.ts", "deprecated": false @@ -2761,7 +2788,15 @@ "signature": [ "(sessionId: string) => Promise<", "SavedObject", - ">" + "<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionSavedObjectAttributes", + "text": "SearchSessionSavedObjectAttributes" + }, + ">>" ], "path": "src/plugins/data/server/search/types.ts", "deprecated": false, @@ -2803,7 +2838,15 @@ "section": "def-server.SavedObjectsFindResponse", "text": "SavedObjectsFindResponse" }, - ">" + "<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionSavedObjectAttributes", + "text": "SearchSessionSavedObjectAttributes" + }, + ", unknown>>" ], "path": "src/plugins/data/server/search/types.ts", "deprecated": false, @@ -2860,7 +2903,15 @@ "label": "updateSession", "description": [], "signature": [ - "(sessionId: string, attributes: Partial) => Promise<", + "(sessionId: string, attributes: Partial<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionSavedObjectAttributes", + "text": "SearchSessionSavedObjectAttributes" + }, + ">) => Promise<", { "pluginId": "core", "scope": "server", @@ -2868,7 +2919,15 @@ "section": "def-server.SavedObjectsUpdateResponse", "text": "SavedObjectsUpdateResponse" }, - ">" + "<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionSavedObjectAttributes", + "text": "SearchSessionSavedObjectAttributes" + }, + ">>" ], "path": "src/plugins/data/server/search/types.ts", "deprecated": false, @@ -2892,7 +2951,27 @@ "label": "attributes", "description": [], "signature": [ - "{ [P in keyof T]?: T[P] | undefined; }" + "{ sessionId?: string | undefined; name?: string | undefined; appId?: string | undefined; created?: string | undefined; touched?: string | undefined; expires?: string | undefined; completed?: string | null | undefined; status?: ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionStatus", + "text": "SearchSessionStatus" + }, + " | undefined; locatorId?: string | undefined; initialState?: ", + "SerializableRecord", + " | undefined; restoreState?: ", + "SerializableRecord", + " | undefined; idMapping?: Record | undefined; persisted?: boolean | undefined; realmType?: string | undefined; realmName?: string | undefined; username?: string | undefined; version?: string | undefined; }" ], "path": "src/plugins/data/server/search/session/types.ts", "deprecated": false @@ -2967,7 +3046,15 @@ "section": "def-server.SavedObjectsUpdateResponse", "text": "SavedObjectsUpdateResponse" }, - ">" + "<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.SearchSessionSavedObjectAttributes", + "text": "SearchSessionSavedObjectAttributes" + }, + ">>" ], "path": "src/plugins/data/server/search/types.ts", "deprecated": false, @@ -3008,16 +3095,6 @@ "tags": [], "label": "ISearchSessionService", "description": [], - "signature": [ - { - "pluginId": "data", - "scope": "server", - "docId": "kibDataSearchPluginApi", - "section": "def-server.ISearchSessionService", - "text": "ISearchSessionService" - }, - "" - ], "path": "src/plugins/data/server/search/session/types.ts", "deprecated": false, "children": [ @@ -3040,8 +3117,7 @@ ") => (request: ", "KibanaRequest", ") => ", - "IScopedSearchSessionsClient", - "" + "IScopedSearchSessionsClient" ], "path": "src/plugins/data/server/search/session/types.ts", "deprecated": false, @@ -3758,8 +3834,7 @@ "label": "searchSessionsClient", "description": [], "signature": [ - "IScopedSearchSessionsClient", - "" + "IScopedSearchSessionsClient" ], "path": "src/plugins/data/server/search/types.ts", "deprecated": false @@ -4481,7 +4556,15 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "" + ">" ], "path": "src/plugins/data/common/search/aggs/agg_config.ts", "deprecated": false, @@ -7126,7 +7209,15 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "" + ">" ], "path": "src/plugins/data/common/search/aggs/agg_type.ts", "deprecated": false, @@ -21671,7 +21762,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">) | undefined" ], diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index b141bc3f7fa82..3b049a1d27a4a 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github summary: API docs for the data.search plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] warning: 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. --- diff --git a/api_docs/data_view_editor.devdocs.json b/api_docs/data_view_editor.devdocs.json index edcf82634ea28..a03f5a4289435 100644 --- a/api_docs/data_view_editor.devdocs.json +++ b/api_docs/data_view_editor.devdocs.json @@ -128,6 +128,21 @@ ], "path": "src/plugins/data_view_editor/public/types.ts", "deprecated": false + }, + { + "parentPluginId": "dataViewEditor", + "id": "def-public.DataViewEditorProps.allowAdHocDataView", + "type": "CompoundType", + "tags": [], + "label": "allowAdHocDataView", + "description": [ + "\nif set to true user is presented with an option to create ad-hoc dataview without a saved object." + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_view_editor/public/types.ts", + "deprecated": false } ], "initialIsOpen": false diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index a0dfcb172f2c8..432e7f61c8b7f 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewEditor plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 14 | 0 | 7 | 0 | +| 15 | 0 | 7 | 0 | ## Client diff --git a/api_docs/data_view_field_editor.devdocs.json b/api_docs/data_view_field_editor.devdocs.json index 8b3e28b5fd93a..7f38835b2639d 100644 --- a/api_docs/data_view_field_editor.devdocs.json +++ b/api_docs/data_view_field_editor.devdocs.json @@ -127,7 +127,7 @@ "label": "onChange", "description": [], "signature": [ - "(newParams?: {}) => void" + "(newParams?: Partial<{ type?: string | undefined; } & P>) => void" ], "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx", "deprecated": false, @@ -140,7 +140,7 @@ "label": "newParams", "description": [], "signature": [ - "{}" + "Partial<{ type?: string | undefined; } & P>" ], "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx", "deprecated": false, @@ -242,7 +242,9 @@ "label": "onChange", "description": [], "signature": [ - "(newParams: { [key: string]: any; }) => void" + "(newParams: ", + "SerializableRecord", + ") => void" ], "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/types.ts", "deprecated": false, @@ -254,23 +256,12 @@ "tags": [], "label": "newParams", "description": [], + "signature": [ + "SerializableRecord" + ], "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/types.ts", "deprecated": false, - "children": [ - { - "parentPluginId": "dataViewFieldEditor", - "id": "def-public.FormatEditorProps.onChange.$1.Unnamed", - "type": "IndexSignature", - "tags": [], - "label": "[key: string]: any", - "description": [], - "signature": [ - "[key: string]: any" - ], - "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/types.ts", - "deprecated": false - } - ] + "isRequired": true } ], "returnComment": [] @@ -556,7 +547,7 @@ "section": "def-public.FieldFormatEditorFactory", "text": "FieldFormatEditorFactory" }, - ") => void; }" + "<{}>) => void; }" ], "path": "src/plugins/data_view_field_editor/public/types.ts", "deprecated": false @@ -679,7 +670,7 @@ "section": "def-public.FieldFormatEditorFactory", "text": "FieldFormatEditorFactory" }, - "[]; getById: (id: string) => ", + "<{}>[]; getById:

(id: string) => ", { "pluginId": "dataViewFieldEditor", "scope": "public", @@ -687,7 +678,7 @@ "section": "def-public.FieldFormatEditorFactory", "text": "FieldFormatEditorFactory" }, - " | undefined; }" + "

| undefined; }" ], "path": "src/plugins/data_view_field_editor/public/types.ts", "deprecated": false diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 59bf59eefe9bd..c985097784af0 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewFieldEditor plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 42 | 0 | 37 | 3 | +| 41 | 0 | 36 | 3 | ## Client diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index d1f57d8a709de..1aeb8bae0d401 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViewManagement plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] warning: 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. --- diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index 1182fdba14c4d..ada9c71be6610 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -1451,7 +1451,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">) => void" ], @@ -1491,7 +1491,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">" ], @@ -1579,7 +1579,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", { @@ -3455,7 +3455,7 @@ "\nCreate a new data view instance." ], "signature": [ - "({ id, ...restOfSpec }: ", + "({ id, name, title, ...restOfSpec }: ", { "pluginId": "dataViews", "scope": "common", @@ -3481,7 +3481,7 @@ "id": "def-public.DataViewsService.create.$1", "type": "Object", "tags": [], - "label": "{ id, ...restOfSpec }", + "label": "{ id, name, title, ...restOfSpec }", "description": [], "signature": [ { @@ -4307,13 +4307,7 @@ "label": "uiSettings", "description": [], "signature": [ - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - } + "IUiSettingsClient" ], "path": "src/plugins/data_views/public/ui_settings_wrapper.ts", "deprecated": false, @@ -5902,7 +5896,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">> | undefined; runtimeFieldMap?: Record | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", { @@ -7555,7 +7549,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">) => void" ], @@ -7595,7 +7589,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">" ], @@ -8770,7 +8764,7 @@ "\nCreate a new data view instance." ], "signature": [ - "({ id, ...restOfSpec }: ", + "({ id, name, title, ...restOfSpec }: ", { "pluginId": "dataViews", "scope": "common", @@ -8796,7 +8790,7 @@ "id": "def-server.DataViewsService.create.$1", "type": "Object", "tags": [], - "label": "{ id, ...restOfSpec }", + "label": "{ id, name, title, ...restOfSpec }", "description": [], "signature": [ { @@ -10240,7 +10234,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", { @@ -13560,7 +13554,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">) => void" ], @@ -13600,7 +13594,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">" ], @@ -13688,7 +13682,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", { @@ -15223,7 +15217,7 @@ "\nCreate a new data view instance." ], "signature": [ - "({ id, ...restOfSpec }: ", + "({ id, name, title, ...restOfSpec }: ", { "pluginId": "dataViews", "scope": "common", @@ -15249,7 +15243,7 @@ "id": "def-common.DataViewsService.create.$1", "type": "Object", "tags": [], - "label": "{ id, ...restOfSpec }", + "label": "{ id, name, title, ...restOfSpec }", "description": [], "signature": [ { @@ -17765,7 +17759,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | null | undefined" ], @@ -18532,7 +18526,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">> | undefined; runtimeFieldMap?: Record> | undefined; runtimeFieldMap?: Record; }" ], @@ -19966,7 +19960,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", { diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index affa6f0e564e2..e54328e677243 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataViews plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] warning: 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. --- diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 7c3260f17f381..f945bfc6e2930 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github summary: API docs for the dataVisualizer plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] warning: 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. --- diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 671d479bbccc2..accd8e8985cbd 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -3,7 +3,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API summary: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- @@ -50,8 +50,8 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | canvas | - | | | canvas | - | | | canvas | - | -| | management, spaces, ml, canvas, cloudSecurityPosture, enterpriseSearch, osquery | - | -| | management, cloudSecurityPosture, enterpriseSearch | - | +| | management, spaces, ml, canvas, enterpriseSearch, osquery | - | +| | management, enterpriseSearch | - | | | enterpriseSearch | - | | | actions, ml, enterpriseSearch, savedObjectsTagging | - | | | spaces, savedObjectsManagement | - | @@ -137,4 +137,5 @@ Safe to remove. | | @kbn/core-http-browser | | | @kbn/core-http-browser | | | @kbn/core-injected-metadata-browser | -| | @kbn/core-injected-metadata-browser | \ No newline at end of file +| | @kbn/core-injected-metadata-browser | +| | @kbn/core-ui-settings-common | \ No newline at end of file diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index fab0384a628df..f5e89b9dd8cba 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -3,7 +3,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin summary: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- @@ -101,8 +101,6 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplateProps), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplateProps), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplateProps), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplateProps), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplateProps), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplateProps), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplateProps), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplateProps), [compliance_dashboard.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx#:~:text=KibanaPageTemplateProps), [compliance_dashboard.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx#:~:text=KibanaPageTemplateProps)+ 2 more | - | -| | [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplate), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplate), [csp_page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx#:~:text=KibanaPageTemplate) | - | | | [app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/application/app.tsx#:~:text=RedirectAppLinks), [app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/application/app.tsx#:~:text=RedirectAppLinks), [app.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/public/application/app.tsx#:~:text=RedirectAppLinks) | - | | | [update_rules_configuration.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/cloud_security_posture/server/routes/configuration/update_rules_configuration.ts#:~:text=authc) | - | @@ -217,7 +215,7 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx#:~:text=KibanaPageTemplateProps), [page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx#:~:text=KibanaPageTemplateProps) | - | -| | [version_mismatch_page.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/version_mismatch/version_mismatch_page.tsx#:~:text=KibanaPageTemplate), [version_mismatch_page.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/version_mismatch/version_mismatch_page.tsx#:~:text=KibanaPageTemplate), [version_mismatch_page.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/version_mismatch/version_mismatch_page.tsx#:~:text=KibanaPageTemplate), [error_connecting.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.tsx#:~:text=KibanaPageTemplate), [error_connecting.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.tsx#:~:text=KibanaPageTemplate), [error_connecting.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.tsx#:~:text=KibanaPageTemplate), [product_selector.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx#:~:text=KibanaPageTemplate), [product_selector.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx#:~:text=KibanaPageTemplate), [product_selector.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx#:~:text=KibanaPageTemplate), [error_connecting.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/error_connecting/error_connecting.tsx#:~:text=KibanaPageTemplate)+ 11 more | - | +| | [version_mismatch_page.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/version_mismatch/version_mismatch_page.tsx#:~:text=KibanaPageTemplate), [version_mismatch_page.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/version_mismatch/version_mismatch_page.tsx#:~:text=KibanaPageTemplate), [version_mismatch_page.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/version_mismatch/version_mismatch_page.tsx#:~:text=KibanaPageTemplate), [error_connecting.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.tsx#:~:text=KibanaPageTemplate), [error_connecting.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.tsx#:~:text=KibanaPageTemplate), [error_connecting.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/error_connecting/error_connecting.tsx#:~:text=KibanaPageTemplate), [page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx#:~:text=KibanaPageTemplate), [page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx#:~:text=KibanaPageTemplate), [page_template.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx#:~:text=KibanaPageTemplate), [error_connecting.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/error_connecting/error_connecting.tsx#:~:text=KibanaPageTemplate)+ 8 more | - | | | [account_settings.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx#:~:text=uiApi), [account_settings.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx#:~:text=uiApi), [account_settings.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx#:~:text=uiApi), [account_settings.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/account_settings/account_settings.tsx#:~:text=uiApi) | - | | | [check_access.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/server/lib/check_access.ts#:~:text=authz), [check_access.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/server/lib/check_access.ts#:~:text=authz), [check_access.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/enterprise_search/server/lib/check_access.ts#:~:text=authz) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 8d5fe5e1eae5d..e5f81aef28c08 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -3,7 +3,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team summary: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index aa54cbe4f050e..39e4ba5303407 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github summary: API docs for the devTools plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] warning: 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. --- diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index f65c671bed195..3af0082f21259 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github summary: API docs for the discover plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] warning: 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. --- diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 0e9c5ec48c255..727a22fc0498e 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the discoverEnhanced plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] warning: 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. --- diff --git a/api_docs/elastic_apm_synthtrace.mdx b/api_docs/elastic_apm_synthtrace.mdx index 5ca22a26a6e36..f78a462730cc7 100644 --- a/api_docs/elastic_apm_synthtrace.mdx +++ b/api_docs/elastic_apm_synthtrace.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/elastic-apm-synthtrace title: "@elastic/apm-synthtrace" image: https://source.unsplash.com/400x175/?github summary: API docs for the @elastic/apm-synthtrace plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@elastic/apm-synthtrace'] warning: 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. --- diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index e4131ab27841b..ee81c48756d34 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github summary: API docs for the embeddable plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] warning: 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. --- diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 57a314069ec80..1acc46793b3b3 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the embeddableEnhanced plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] warning: 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. --- diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 6d81ac8710d6d..ec4f75ec8fee2 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the encryptedSavedObjects plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] warning: 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. --- diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index e63cd6c903d56..2706a8d892b0d 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github summary: API docs for the enterpriseSearch plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] warning: 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. --- diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 9af8efc8273f8..695e0246b3fa1 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github summary: API docs for the esUiShared plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] warning: 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. --- diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index ef1af364265bd..00254b6bdf741 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github summary: API docs for the eventAnnotation plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] warning: 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. --- diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 8f4e382d5481b..0ccfe05f61b4b 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github summary: API docs for the eventLog plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] warning: 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. --- diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 51094be114475..4bb6a0debe5f2 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionError plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] warning: 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. --- diff --git a/api_docs/expression_gauge.devdocs.json b/api_docs/expression_gauge.devdocs.json index c3acd6e8b013f..89a17fbf23fa0 100644 --- a/api_docs/expression_gauge.devdocs.json +++ b/api_docs/expression_gauge.devdocs.json @@ -898,7 +898,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined) => ", { @@ -928,7 +928,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined" ], diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index e50484b266e4c..6cff0a59c29ff 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionGauge plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] warning: 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. --- diff --git a/api_docs/expression_heatmap.devdocs.json b/api_docs/expression_heatmap.devdocs.json index 0a8c0f54bc641..6cc1961115e4e 100644 --- a/api_docs/expression_heatmap.devdocs.json +++ b/api_docs/expression_heatmap.devdocs.json @@ -485,7 +485,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined) => ", { @@ -515,7 +515,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined" ], diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 685f99a7ba9e0..b9a4b3dffb298 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionHeatmap plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] warning: 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. --- diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 2e1f71c8bdd5c..f229794d468b6 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionImage plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] warning: 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. --- diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 9e6300966a37f..d4a796f2a1c96 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionLegacyMetricVis plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] warning: 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. --- diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index e8985aa1d6ed7..26fab7967f41d 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionMetric plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] warning: 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. --- diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index ed1d2c1b8385d..b40a98b6ea614 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionMetricVis plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] warning: 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. --- diff --git a/api_docs/expression_partition_vis.devdocs.json b/api_docs/expression_partition_vis.devdocs.json index 215825a71615f..2f6134f683007 100644 --- a/api_docs/expression_partition_vis.devdocs.json +++ b/api_docs/expression_partition_vis.devdocs.json @@ -253,7 +253,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; }" ], diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 0dc3ea7c83883..6d98ffe4574e4 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionPartitionVis plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] warning: 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. --- diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index fff23cee1715b..83847cbfa20eb 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionRepeatImage plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] warning: 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. --- diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 03329e37a283c..af10452b79ad9 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionRevealImage plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] warning: 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. --- diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index e9b3fd2668ae8..ad054fb3a2471 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionShape plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] warning: 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. --- diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 1cf371bedce39..f96fdb83a86aa 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionTagcloud plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] warning: 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. --- diff --git a/api_docs/expression_x_y.devdocs.json b/api_docs/expression_x_y.devdocs.json index 8e4323a0f0114..4f47ae934bf4d 100644 --- a/api_docs/expression_x_y.devdocs.json +++ b/api_docs/expression_x_y.devdocs.json @@ -96,10 +96,10 @@ }, { "parentPluginId": "expressionXY", - "id": "def-common.AnnotationLayerArgs.hide", + "id": "def-common.AnnotationLayerArgs.simpleView", "type": "CompoundType", "tags": [], - "label": "hide", + "label": "simpleView", "description": [], "signature": [ "boolean | undefined" @@ -582,10 +582,10 @@ }, { "parentPluginId": "expressionXY", - "id": "def-common.DataLayerArgs.hide", + "id": "def-common.DataLayerArgs.simpleView", "type": "CompoundType", "tags": [], - "label": "hide", + "label": "simpleView", "description": [], "signature": [ "boolean | undefined" diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 07590478a7e0e..769711dd20f83 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressionXY plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] warning: 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. --- diff --git a/api_docs/expressions.devdocs.json b/api_docs/expressions.devdocs.json index bea645fca66b1..dd9b0e90dcf4c 100644 --- a/api_docs/expressions.devdocs.json +++ b/api_docs/expressions.devdocs.json @@ -27942,7 +27942,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined" ], diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index f8c304a1aeab4..f801f706d9171 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github summary: API docs for the expressions plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] warning: 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. --- diff --git a/api_docs/features.mdx b/api_docs/features.mdx index d6353777ae421..b8902e45cf670 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github summary: API docs for the features plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] warning: 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. --- diff --git a/api_docs/field_formats.devdocs.json b/api_docs/field_formats.devdocs.json index 1fbc728768522..6ee4a0284f9f5 100644 --- a/api_docs/field_formats.devdocs.json +++ b/api_docs/field_formats.devdocs.json @@ -2116,7 +2116,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined) => ", { @@ -2145,7 +2145,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined" ], @@ -4878,7 +4878,8 @@ "\nParams provided when creating a formatter.\nParams are vary per formatter\n\nTODO: support strict typing for params depending on format type\nhttps://github.com/elastic/kibana/issues/108158" ], "signature": [ - "SerializableRecord" + "SerializableRecord", + " & P" ], "path": "src/plugins/field_formats/common/types.ts", "deprecated": false, @@ -5082,7 +5083,7 @@ "label": "FormatFactory", "description": [], "signature": [ - "(mapping?: ", + "

(mapping?: ", { "pluginId": "fieldFormats", "scope": "common", @@ -5090,9 +5091,15 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", - "SerializableRecord", - "> | undefined) => ", + "> | undefined) => ", { "pluginId": "fieldFormats", "scope": "common", @@ -5120,9 +5127,15 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", - "SerializableRecord", - "> | undefined" + "> | undefined" ], "path": "src/plugins/field_formats/common/types.ts", "deprecated": false diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 3f308b1e45891..5275befa23274 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github summary: API docs for the fieldFormats plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] warning: 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. --- diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 0a0984a7c1b61..11b4fed345f4e 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github summary: API docs for the fileUpload plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] warning: 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. --- diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 0e8db05a8eb7a..08aa1d377af7d 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -564,6 +564,19 @@ "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", "deprecated": false }, + { + "parentPluginId": "fleet", + "id": "def-public.NewPackagePolicy.is_managed", + "type": "CompoundType", + "tags": [], + "label": "is_managed", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", + "deprecated": false + }, { "parentPluginId": "fleet", "id": "def-public.NewPackagePolicy.policy_id", @@ -1342,7 +1355,7 @@ "The updated Integration Policy to be merged back and included in the API call" ], "signature": [ - "{ id?: string | number | undefined; name?: string | undefined; description?: string | undefined; namespace?: string | undefined; enabled?: boolean | undefined; policy_id?: string | undefined; output_id?: string | undefined; package?: ", + "{ id?: string | number | undefined; name?: string | undefined; description?: string | undefined; namespace?: string | undefined; enabled?: boolean | undefined; is_managed?: boolean | undefined; policy_id?: string | undefined; output_id?: string | undefined; package?: ", { "pluginId": "fleet", "scope": "common", @@ -2981,6 +2994,38 @@ ], "returnComment": [] }, + { + "parentPluginId": "fleet", + "id": "def-public.pagePathGetters.settings_edit_download_sources", + "type": "Function", + "tags": [], + "label": "settings_edit_download_sources", + "description": [], + "signature": [ + "({ downloadSourceId }: ", + "DynamicPagePathValues", + ") => [string, string]" + ], + "path": "x-pack/plugins/fleet/public/constants/page_paths.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-public.pagePathGetters.settings_edit_download_sources.$1", + "type": "Object", + "tags": [], + "label": "{ downloadSourceId }", + "description": [], + "signature": [ + "DynamicPagePathValues" + ], + "path": "x-pack/plugins/fleet/public/constants/page_paths.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-public.pagePathGetters.settings_create_outputs", @@ -2996,6 +3041,21 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "fleet", + "id": "def-public.pagePathGetters.settings_create_download_sources", + "type": "Function", + "tags": [], + "label": "settings_create_download_sources", + "description": [], + "signature": [ + "() => [string, string]" + ], + "path": "x-pack/plugins/fleet/public/constants/page_paths.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-public.pagePathGetters.debug", @@ -10545,6 +10605,19 @@ "description": [], "path": "x-pack/plugins/fleet/common/types/models/agent_policy.ts", "deprecated": false + }, + { + "parentPluginId": "fleet", + "id": "def-common.AgentPolicy.agents", + "type": "number", + "tags": [], + "label": "agents", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/agent_policy.ts", + "deprecated": false } ], "initialIsOpen": false @@ -16436,6 +16509,19 @@ "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", "deprecated": false }, + { + "parentPluginId": "fleet", + "id": "def-common.NewPackagePolicy.is_managed", + "type": "CompoundType", + "tags": [], + "label": "is_managed", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", + "deprecated": false + }, { "parentPluginId": "fleet", "id": "def-common.NewPackagePolicy.policy_id", @@ -17745,7 +17831,7 @@ "label": "body", "description": [], "signature": [ - "{ id: string; name: string; hosts: string; is_default?: boolean | undefined; }" + "{ id?: string | undefined; name: string; host: string; is_default?: boolean | undefined; }" ], "path": "x-pack/plugins/fleet/common/types/rest_spec/download_sources.ts", "deprecated": false @@ -18257,7 +18343,7 @@ "label": "body", "description": [], "signature": [ - "{ id: string; name: string; hosts: string; is_default?: boolean | undefined; }" + "{ name: string; host: string; is_default?: boolean | undefined; }" ], "path": "x-pack/plugins/fleet/common/types/rest_spec/download_sources.ts", "deprecated": false @@ -20222,7 +20308,7 @@ "section": "def-common.ValueOf", "text": "ValueOf" }, - "<{ readonly Active: \"active\"; readonly Inactive: \"inactive\"; }>; description?: string | undefined; name: string; updated_at: string; namespace: string; updated_by: string; is_default?: boolean | undefined; is_default_fleet_server?: boolean | undefined; has_fleet_server?: boolean | undefined; is_managed: boolean; monitoring_enabled?: (\"metrics\" | \"logs\")[] | undefined; unenroll_timeout?: number | undefined; is_preconfigured?: boolean | undefined; data_output_id?: string | null | undefined; monitoring_output_id?: string | null | undefined; download_source_id?: string | null | undefined; package_policies: string[] | ", + "<{ readonly Active: \"active\"; readonly Inactive: \"inactive\"; }>; description?: string | undefined; name: string; updated_at: string; namespace: string; updated_by: string; is_managed: boolean; is_default?: boolean | undefined; is_default_fleet_server?: boolean | undefined; has_fleet_server?: boolean | undefined; monitoring_enabled?: (\"metrics\" | \"logs\")[] | undefined; unenroll_timeout?: number | undefined; is_preconfigured?: boolean | undefined; data_output_id?: string | null | undefined; monitoring_output_id?: string | null | undefined; download_source_id?: string | null | undefined; package_policies: string[] | ", { "pluginId": "fleet", "scope": "common", @@ -20230,7 +20316,7 @@ "section": "def-common.PackagePolicy", "text": "PackagePolicy" }, - "[]; revision: number; }" + "[]; revision: number; agents?: number | undefined; }" ], "path": "x-pack/plugins/fleet/common/types/models/agent_policy.ts", "deprecated": false, @@ -20604,13 +20690,13 @@ }, { "parentPluginId": "fleet", - "id": "def-common.DEFAULT_DOWNLOAD_SOURCE", + "id": "def-common.DEFAULT_DOWNLOAD_SOURCE_ID", "type": "string", "tags": [], - "label": "DEFAULT_DOWNLOAD_SOURCE", + "label": "DEFAULT_DOWNLOAD_SOURCE_ID", "description": [], "signature": [ - "\"https://artifacts.elastic.co\"" + "\"fleet-default-download-source\"" ], "path": "x-pack/plugins/fleet/common/constants/download_source.ts", "deprecated": false, @@ -20618,13 +20704,13 @@ }, { "parentPluginId": "fleet", - "id": "def-common.DEFAULT_DOWNLOAD_SOURCE_ID", + "id": "def-common.DEFAULT_DOWNLOAD_SOURCE_URI", "type": "string", "tags": [], - "label": "DEFAULT_DOWNLOAD_SOURCE_ID", + "label": "DEFAULT_DOWNLOAD_SOURCE_URI", "description": [], "signature": [ - "\"fleet-default-download-source\"" + "\"https://artifacts.elastic.co/downloads/beats/elastic-agent\"" ], "path": "x-pack/plugins/fleet/common/constants/download_source.ts", "deprecated": false, @@ -21274,8 +21360,8 @@ "pluginId": "fleet", "scope": "common", "docId": "kibFleetPluginApi", - "section": "def-common.DownloadSourceBase", - "text": "DownloadSourceBase" + "section": "def-common.DownloadSource", + "text": "DownloadSource" }, ">" ], @@ -22293,7 +22379,7 @@ "section": "def-common.PackagePolicyInput", "text": "PackagePolicyInput" }, - "[]; policy_id: string; output_id: string; revision: number; }" + "[]; is_managed?: boolean | undefined; policy_id: string; output_id: string; revision: number; }" ], "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", "deprecated": false, @@ -24315,6 +24401,139 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService", + "type": "Object", + "tags": [], + "label": "downloadSourceRoutesService", + "description": [], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService.getInfoPath", + "type": "Function", + "tags": [], + "label": "getInfoPath", + "description": [], + "signature": [ + "(downloadSourceId: string) => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService.getInfoPath.$1", + "type": "string", + "tags": [], + "label": "downloadSourceId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService.getUpdatePath", + "type": "Function", + "tags": [], + "label": "getUpdatePath", + "description": [], + "signature": [ + "(downloadSourceId: string) => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService.getUpdatePath.$1", + "type": "string", + "tags": [], + "label": "downloadSourceId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService.getListPath", + "type": "Function", + "tags": [], + "label": "getListPath", + "description": [], + "signature": [ + "() => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService.getDeletePath", + "type": "Function", + "tags": [], + "label": "getDeletePath", + "description": [], + "signature": [ + "(downloadSourceId: string) => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService.getDeletePath.$1", + "type": "string", + "tags": [], + "label": "downloadSourceId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-common.downloadSourceRoutesService.getCreatePath", + "type": "Function", + "tags": [], + "label": "getCreatePath", + "description": [], + "signature": [ + "() => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-common.ENROLLMENT_API_KEY_ROUTES", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 9e4d8abbf4299..aca1a18de9763 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github summary: API docs for the fleet plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1522 | 8 | 1390 | 10 | +| 1537 | 8 | 1405 | 10 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index dd60d001c83c5..f509bbceab1bb 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github summary: API docs for the globalSearch plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] warning: 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. --- diff --git a/api_docs/home.mdx b/api_docs/home.mdx index dcf20af6a1d11..8e85eec907cb5 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github summary: API docs for the home plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] warning: 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. --- diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index c806e66c7e64b..3ddfa9472cee9 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the indexLifecycleManagement plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] warning: 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. --- diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 05e767cf2fc4c..20c5fae345e14 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the indexManagement plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] warning: 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. --- diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index d2c9347b374b5..46b09dd487976 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github summary: API docs for the infra plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] warning: 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. --- diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index db6eb55ddad01..489d0c62ca73d 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github summary: API docs for the inspector plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] warning: 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. --- diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 632870059bc83..df6d98288a7e6 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github summary: API docs for the interactiveSetup plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] warning: 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. --- diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index d33da0ffedfeb..bfacf8594eae2 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ace plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] warning: 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. --- diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 67908b73aaf91..93a67041fd5e1 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/aiops-components plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] warning: 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. --- diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 16b93b3725319..759aaa0bc0dfe 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/aiops-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] warning: 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. --- diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 50b568cc1982a..90342956e9186 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/alerts plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] warning: 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. --- diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 13aa2734bd079..04f13d4eb9fb1 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] warning: 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. --- diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 276c72a842dfc..2e1deba00597b 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics-client plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] warning: 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. --- diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 4b9a8759b2b1b..e2f1ec1edbf6f 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] warning: 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. --- diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index 7e0390fc7d255..b5f800cc45217 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] warning: 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. --- diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 8e9c1a191211b..b57ef26af2ffd 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] warning: 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. --- diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 17813d56492b2..197f236a44afc 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] warning: 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. --- diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 5c00309bd8842..4851a89f604ff 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/apm-config-loader plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] warning: 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. --- diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 5203af444072a..275b0af889913 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/apm-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] warning: 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. --- diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index c94abfadcbe05..1fff24880c847 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/axe-config plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] warning: 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. --- diff --git a/api_docs/kbn_bazel_packages.mdx b/api_docs/kbn_bazel_packages.mdx index 99c31ede3a39d..a748a89fa5a6e 100644 --- a/api_docs/kbn_bazel_packages.mdx +++ b/api_docs/kbn_bazel_packages.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-bazel-packages title: "@kbn/bazel-packages" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/bazel-packages plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bazel-packages'] warning: 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. --- diff --git a/api_docs/kbn_bazel_runner.mdx b/api_docs/kbn_bazel_runner.mdx index 6d99f6c5f5299..8e0ad755b916d 100644 --- a/api_docs/kbn_bazel_runner.mdx +++ b/api_docs/kbn_bazel_runner.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-bazel-runner title: "@kbn/bazel-runner" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/bazel-runner plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bazel-runner'] warning: 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. --- diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index dc14fb459eb97..d451df11ab8f7 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ci-stats-core plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] warning: 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. --- diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index 38dc0a15f5175..a08924d9a36fd 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] warning: 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. --- diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 869643ad84802..04f72f64ea26b 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] warning: 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. --- diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 15587ab667343..a60a7bd922d72 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/cli-dev-mode plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] warning: 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. --- diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 471a883e4db00..336107bb56a36 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/coloring plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] warning: 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. --- diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index e3f717c4d980a..51cf363418db2 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/config plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] warning: 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. --- diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index c8d686e8deda8..4a51e79032b03 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/config-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] warning: 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. --- diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index a9387c456838b..c7b2409974ec3 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/config-schema plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] warning: 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. --- diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 2fc459ffbbe1a..34c0235b4c88d 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] warning: 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. --- diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index c28cc9230262a..d7c914cb8bee7 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index c3dea4bb4fec1..7e3d75a06cdeb 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index f2f99d527dd31..a41b00c3a0369 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-server plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] warning: 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. --- diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index e6e247e4970ab..2d22e691556b7 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 92e3d24c1bedb..c2f4be79eea09 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index ad6288df80ee0..982afbb257220 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index ba1e4abd15ae2..a12a0574d2d09 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-base-common plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] warning: 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. --- diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index c7d4e0c80c19e..570e4cddb26df 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-base-server-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index d2b99c2f95faf..ea34e4e8e279c 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 9c7741208effb..f0950bc88cf6f 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-config-server-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_deprecations_browser.devdocs.json b/api_docs/kbn_core_deprecations_browser.devdocs.json new file mode 100644 index 0000000000000..76ea9b00bad48 --- /dev/null +++ b/api_docs/kbn_core_deprecations_browser.devdocs.json @@ -0,0 +1,189 @@ +{ + "id": "@kbn/core-deprecations-browser", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.DeprecationsServiceStart", + "type": "Interface", + "tags": [], + "label": "DeprecationsServiceStart", + "description": [ + "\nDeprecationsService provides methods to fetch domain deprecation details from\nthe Kibana server.\n" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/contracts.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.DeprecationsServiceStart.getAllDeprecations", + "type": "Function", + "tags": [], + "label": "getAllDeprecations", + "description": [ + "\nGrabs deprecations details for all domains." + ], + "signature": [ + "() => Promise<", + "DomainDeprecationDetails", + "[]>" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/contracts.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.DeprecationsServiceStart.getDeprecations", + "type": "Function", + "tags": [], + "label": "getDeprecations", + "description": [ + "\nGrabs deprecations for a specific domain.\n" + ], + "signature": [ + "(domainId: string) => Promise<", + "DomainDeprecationDetails", + "[]>" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/contracts.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.DeprecationsServiceStart.getDeprecations.$1", + "type": "string", + "tags": [], + "label": "domainId", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/contracts.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.DeprecationsServiceStart.isDeprecationResolvable", + "type": "Function", + "tags": [], + "label": "isDeprecationResolvable", + "description": [ + "\nReturns a boolean if the provided deprecation can be automatically resolvable.\n" + ], + "signature": [ + "(details: ", + "DomainDeprecationDetails", + ") => boolean" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/contracts.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.DeprecationsServiceStart.isDeprecationResolvable.$1", + "type": "CompoundType", + "tags": [], + "label": "details", + "description": [], + "signature": [ + "DomainDeprecationDetails" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/contracts.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.DeprecationsServiceStart.resolveDeprecation", + "type": "Function", + "tags": [], + "label": "resolveDeprecation", + "description": [ + "\nCalls the correctiveActions.api to automatically resolve the depprecation.\n" + ], + "signature": [ + "(details: ", + "DomainDeprecationDetails", + ") => Promise<", + { + "pluginId": "@kbn/core-deprecations-browser", + "scope": "common", + "docId": "kibKbnCoreDeprecationsBrowserPluginApi", + "section": "def-common.ResolveDeprecationResponse", + "text": "ResolveDeprecationResponse" + }, + ">" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/contracts.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.DeprecationsServiceStart.resolveDeprecation.$1", + "type": "CompoundType", + "tags": [], + "label": "details", + "description": [], + "signature": [ + "DomainDeprecationDetails" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/contracts.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-deprecations-browser", + "id": "def-common.ResolveDeprecationResponse", + "type": "Type", + "tags": [], + "label": "ResolveDeprecationResponse", + "description": [ + "\nResponse from correctiveActions.api call from automatically resolving the deprecation" + ], + "signature": [ + "{ status: \"ok\"; } | { status: \"fail\"; reason: string; }" + ], + "path": "packages/core/deprecations/core-deprecations-browser/src/types.ts", + "deprecated": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx new file mode 100644 index 0000000000000..d8065d5402b0e --- /dev/null +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -0,0 +1,30 @@ +--- +id: kibKbnCoreDeprecationsBrowserPluginApi +slug: /kibana-dev-docs/api/kbn-core-deprecations-browser +title: "@kbn/core-deprecations-browser" +image: https://source.unsplash.com/400x175/?github +summary: API docs for the @kbn/core-deprecations-browser plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] +warning: 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. +--- +import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 9 | 0 | 3 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_deprecations_browser_internal.devdocs.json b/api_docs/kbn_core_deprecations_browser_internal.devdocs.json new file mode 100644 index 0000000000000..3d549b7a15850 --- /dev/null +++ b/api_docs/kbn_core_deprecations_browser_internal.devdocs.json @@ -0,0 +1,129 @@ +{ + "id": "@kbn/core-deprecations-browser-internal", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [ + { + "parentPluginId": "@kbn/core-deprecations-browser-internal", + "id": "def-common.DeprecationsService", + "type": "Class", + "tags": [], + "label": "DeprecationsService", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-deprecations-browser-internal", + "scope": "common", + "docId": "kibKbnCoreDeprecationsBrowserInternalPluginApi", + "section": "def-common.DeprecationsService", + "text": "DeprecationsService" + }, + " implements ", + "CoreService", + "" + ], + "path": "packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-browser-internal", + "id": "def-common.DeprecationsService.setup", + "type": "Function", + "tags": [], + "label": "setup", + "description": [], + "signature": [ + "() => void" + ], + "path": "packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-deprecations-browser-internal", + "id": "def-common.DeprecationsService.start", + "type": "Function", + "tags": [], + "label": "start", + "description": [], + "signature": [ + "({ http }: { http: ", + "HttpSetup", + "; }) => ", + "DeprecationsServiceStart" + ], + "path": "packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-browser-internal", + "id": "def-common.DeprecationsService.start.$1", + "type": "Object", + "tags": [], + "label": "{ http }", + "description": [], + "path": "packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-browser-internal", + "id": "def-common.DeprecationsService.start.$1.http", + "type": "Object", + "tags": [], + "label": "http", + "description": [], + "signature": [ + "HttpSetup" + ], + "path": "packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts", + "deprecated": false + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-deprecations-browser-internal", + "id": "def-common.DeprecationsService.stop", + "type": "Function", + "tags": [], + "label": "stop", + "description": [], + "signature": [ + "() => void" + ], + "path": "packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts", + "deprecated": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx new file mode 100644 index 0000000000000..55afc0d1e3e6a --- /dev/null +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -0,0 +1,27 @@ +--- +id: kibKbnCoreDeprecationsBrowserInternalPluginApi +slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal +title: "@kbn/core-deprecations-browser-internal" +image: https://source.unsplash.com/400x175/?github +summary: API docs for the @kbn/core-deprecations-browser-internal plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] +warning: 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. +--- +import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 6 | 0 | 6 | 0 | + +## Common + +### Classes + + diff --git a/api_docs/kbn_core_deprecations_browser_mocks.devdocs.json b/api_docs/kbn_core_deprecations_browser_mocks.devdocs.json new file mode 100644 index 0000000000000..6a3c846f820ae --- /dev/null +++ b/api_docs/kbn_core_deprecations_browser_mocks.devdocs.json @@ -0,0 +1,92 @@ +{ + "id": "@kbn/core-deprecations-browser-mocks", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [ + { + "parentPluginId": "@kbn/core-deprecations-browser-mocks", + "id": "def-common.deprecationsServiceMock", + "type": "Object", + "tags": [], + "label": "deprecationsServiceMock", + "description": [], + "path": "packages/core/deprecations/core-deprecations-browser-mocks/src/deprecations_service.mock.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-browser-mocks", + "id": "def-common.deprecationsServiceMock.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "() => jest.Mocked<", + "PublicMethodsOf", + "<", + "DeprecationsService", + ">>" + ], + "path": "packages/core/deprecations/core-deprecations-browser-mocks/src/deprecations_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-deprecations-browser-mocks", + "id": "def-common.deprecationsServiceMock.createSetupContract", + "type": "Function", + "tags": [], + "label": "createSetupContract", + "description": [], + "signature": [ + "() => undefined" + ], + "path": "packages/core/deprecations/core-deprecations-browser-mocks/src/deprecations_service.mock.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-deprecations-browser-mocks", + "id": "def-common.deprecationsServiceMock.createStartContract", + "type": "Function", + "tags": [], + "label": "createStartContract", + "description": [], + "signature": [ + "() => jest.Mocked<", + "DeprecationsServiceStart", + ">" + ], + "path": "packages/core/deprecations/core-deprecations-browser-mocks/src/deprecations_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + } + ], + "initialIsOpen": false + } + ] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx new file mode 100644 index 0000000000000..3548f24bc7dec --- /dev/null +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -0,0 +1,27 @@ +--- +id: kibKbnCoreDeprecationsBrowserMocksPluginApi +slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks +title: "@kbn/core-deprecations-browser-mocks" +image: https://source.unsplash.com/400x175/?github +summary: API docs for the @kbn/core-deprecations-browser-mocks plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] +warning: 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. +--- +import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 4 | 0 | 4 | 0 | + +## Common + +### Objects + + diff --git a/api_docs/kbn_core_deprecations_common.devdocs.json b/api_docs/kbn_core_deprecations_common.devdocs.json new file mode 100644 index 0000000000000..bdaa9bdad8fd6 --- /dev/null +++ b/api_docs/kbn_core_deprecations_common.devdocs.json @@ -0,0 +1,321 @@ +{ + "id": "@kbn/core-deprecations-common", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.BaseDeprecationDetails", + "type": "Interface", + "tags": [], + "label": "BaseDeprecationDetails", + "description": [ + "\nBase properties shared by all types of deprecations\n" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.BaseDeprecationDetails.title", + "type": "string", + "tags": [], + "label": "title", + "description": [ + "\nThe title of the deprecation.\nCheck the README for writing deprecations in `src/core/server/deprecations/README.mdx`" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.BaseDeprecationDetails.message", + "type": "string", + "tags": [], + "label": "message", + "description": [ + "\nThe description message to be displayed for the deprecation.\nCheck the README for writing deprecations in `src/core/server/deprecations/README.mdx`" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.BaseDeprecationDetails.level", + "type": "CompoundType", + "tags": [], + "label": "level", + "description": [ + "\nlevels:\n- warning: will not break deployment upon upgrade\n- critical: needs to be addressed before upgrade.\n- fetch_error: Deprecations service failed to grab the deprecation details for the domain." + ], + "signature": [ + "\"warning\" | \"critical\" | \"fetch_error\"" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.BaseDeprecationDetails.deprecationType", + "type": "CompoundType", + "tags": [], + "label": "deprecationType", + "description": [ + "\n(optional) Used to identify between different deprecation types.\nExample use case: in Upgrade Assistant, we may want to allow the user to sort by\ndeprecation type or show each type in a separate tab.\n\nFeel free to add new types if necessary.\nPredefined types are necessary to reduce having similar definitions with different keywords\nacross kibana deprecations." + ], + "signature": [ + "\"config\" | \"feature\" | undefined" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.BaseDeprecationDetails.documentationUrl", + "type": "string", + "tags": [], + "label": "documentationUrl", + "description": [ + "(optional) link to the documentation for more details on the deprecation." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.BaseDeprecationDetails.requireRestart", + "type": "CompoundType", + "tags": [], + "label": "requireRestart", + "description": [ + "(optional) specify the fix for this deprecation requires a full kibana restart." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.BaseDeprecationDetails.correctiveActions", + "type": "Object", + "tags": [], + "label": "correctiveActions", + "description": [ + "corrective action needed to fix this deprecation." + ], + "signature": [ + "{ api?: { path: string; method: \"POST\" | \"PUT\"; body?: { [key: string]: any; } | undefined; omitContextFromBody?: boolean | undefined; } | undefined; manualSteps: string[]; }" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.ConfigDeprecationDetails", + "type": "Interface", + "tags": [], + "label": "ConfigDeprecationDetails", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-deprecations-common", + "scope": "common", + "docId": "kibKbnCoreDeprecationsCommonPluginApi", + "section": "def-common.ConfigDeprecationDetails", + "text": "ConfigDeprecationDetails" + }, + " extends ", + { + "pluginId": "@kbn/core-deprecations-common", + "scope": "common", + "docId": "kibKbnCoreDeprecationsCommonPluginApi", + "section": "def-common.BaseDeprecationDetails", + "text": "BaseDeprecationDetails" + } + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.ConfigDeprecationDetails.configPath", + "type": "string", + "tags": [], + "label": "configPath", + "description": [], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.ConfigDeprecationDetails.deprecationType", + "type": "string", + "tags": [], + "label": "deprecationType", + "description": [], + "signature": [ + "\"config\"" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.DeprecationsGetResponse", + "type": "Interface", + "tags": [], + "label": "DeprecationsGetResponse", + "description": [], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.DeprecationsGetResponse.deprecations", + "type": "Array", + "tags": [], + "label": "deprecations", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-deprecations-common", + "scope": "common", + "docId": "kibKbnCoreDeprecationsCommonPluginApi", + "section": "def-common.DomainDeprecationDetails", + "text": "DomainDeprecationDetails" + }, + "[]" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.FeatureDeprecationDetails", + "type": "Interface", + "tags": [], + "label": "FeatureDeprecationDetails", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-deprecations-common", + "scope": "common", + "docId": "kibKbnCoreDeprecationsCommonPluginApi", + "section": "def-common.FeatureDeprecationDetails", + "text": "FeatureDeprecationDetails" + }, + " extends ", + { + "pluginId": "@kbn/core-deprecations-common", + "scope": "common", + "docId": "kibKbnCoreDeprecationsCommonPluginApi", + "section": "def-common.BaseDeprecationDetails", + "text": "BaseDeprecationDetails" + } + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.FeatureDeprecationDetails.deprecationType", + "type": "string", + "tags": [], + "label": "deprecationType", + "description": [], + "signature": [ + "\"feature\" | undefined" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.DeprecationsDetails", + "type": "Type", + "tags": [], + "label": "DeprecationsDetails", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-deprecations-common", + "scope": "common", + "docId": "kibKbnCoreDeprecationsCommonPluginApi", + "section": "def-common.ConfigDeprecationDetails", + "text": "ConfigDeprecationDetails" + }, + " | ", + { + "pluginId": "@kbn/core-deprecations-common", + "scope": "common", + "docId": "kibKbnCoreDeprecationsCommonPluginApi", + "section": "def-common.FeatureDeprecationDetails", + "text": "FeatureDeprecationDetails" + } + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-deprecations-common", + "id": "def-common.DomainDeprecationDetails", + "type": "Type", + "tags": [], + "label": "DomainDeprecationDetails", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-deprecations-common", + "scope": "common", + "docId": "kibKbnCoreDeprecationsCommonPluginApi", + "section": "def-common.DeprecationsDetails", + "text": "DeprecationsDetails" + }, + " & { domainId: string; }" + ], + "path": "packages/core/deprecations/core-deprecations-common/src/types.ts", + "deprecated": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx new file mode 100644 index 0000000000000..7cdd0a314b3ed --- /dev/null +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -0,0 +1,30 @@ +--- +id: kibKbnCoreDeprecationsCommonPluginApi +slug: /kibana-dev-docs/api/kbn-core-deprecations-common +title: "@kbn/core-deprecations-common" +image: https://source.unsplash.com/400x175/?github +summary: API docs for the @kbn/core-deprecations-common plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] +warning: 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. +--- +import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 17 | 0 | 9 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 1a969e948111d..0381f04c12396 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] warning: 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. --- diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index cd9441faafeae..de58a5bc97d27 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index e960e0a78e180..5c97d175554aa 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-doc-links-server plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] warning: 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. --- diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 6fcdb8e176c21..dce0e80b7bf61 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 51a204698e524..635ed17110cde 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index d430edc47a08a..3070f1b155433 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 83698a759bb1b..2d94f5be05601 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] warning: 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. --- diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index ea919a39c9a6d..100e0917a7ccb 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 05abf8327f857..b1f5cf073486c 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 959a2dbc027ba..31b21911b773f 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-common plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] warning: 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. --- diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index a88ed431d022f..255181e4e8d41 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-execution-context-server plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] warning: 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. --- diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 22d3cdf2819ec..74530da369a26 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 368b325e127a5..f6355f3428056 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index a7b2329ec2369..0863e4d600f6a 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] warning: 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. --- diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index bfea5fb0095d6..25fdf453e6036 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 742d0816a7548..2d831bafc863c 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-http-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] warning: 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. --- diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index c6859f2ef93e6..6545f83989e88 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index df680225c6251..c3794d0a87f1e 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 97ec4742c8089..8a5d8d7e0cb98 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-http-common plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] warning: 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. --- diff --git a/api_docs/kbn_core_http_context_server_mocks.devdocs.json b/api_docs/kbn_core_http_context_server_mocks.devdocs.json new file mode 100644 index 0000000000000..2c77ba329d06d --- /dev/null +++ b/api_docs/kbn_core_http_context_server_mocks.devdocs.json @@ -0,0 +1,201 @@ +{ + "id": "@kbn/core-http-context-server-mocks", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.ContextContainerMock", + "type": "Type", + "tags": [], + "label": "ContextContainerMock", + "description": [], + "signature": [ + "{ registerContext: jest.MockInstance<", + "IContextContainer", + ", [pluginOpaqueId: symbol, contextName: \"resolve\", provider: ", + "IContextProvider", + "<", + "RequestHandlerContextBase", + ", \"resolve\">]>; createHandler: jest.MockInstance<(request: ", + "KibanaRequest", + ", response: ", + "KibanaResponseFactory", + ") => Promise<", + "IKibanaResponse", + ">, [pluginOpaqueId: symbol, handler: ", + "RequestHandler", + "]>; } & ", + "IContextContainer" + ], + "path": "packages/core/http/core-http-context-server-mocks/src/context_container.mock.ts", + "deprecated": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextMock", + "type": "Object", + "tags": [], + "label": "contextMock", + "description": [], + "path": "packages/core/http/core-http-context-server-mocks/src/context_container.mock.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextMock.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "(mockContext?: any) => ", + { + "pluginId": "@kbn/core-http-context-server-mocks", + "scope": "server", + "docId": "kibKbnCoreHttpContextServerMocksPluginApi", + "section": "def-server.ContextContainerMock", + "text": "ContextContainerMock" + } + ], + "path": "packages/core/http/core-http-context-server-mocks/src/context_container.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextMock.create.$1", + "type": "Any", + "tags": [], + "label": "mockContext", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-context-server-mocks/src/context_container.mock.ts", + "deprecated": false + } + ] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextServiceMock", + "type": "Object", + "tags": [], + "label": "contextServiceMock", + "description": [], + "path": "packages/core/http/core-http-context-server-mocks/src/context_service.mock.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextServiceMock.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "() => jest.Mocked" + ], + "path": "packages/core/http/core-http-context-server-mocks/src/context_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextServiceMock.createPrebootContract", + "type": "Function", + "tags": [], + "label": "createPrebootContract", + "description": [], + "signature": [ + "(mockContext?: {}) => jest.Mocked<", + "InternalContextSetup", + ">" + ], + "path": "packages/core/http/core-http-context-server-mocks/src/context_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextServiceMock.createPrebootContract.$1", + "type": "Object", + "tags": [], + "label": "mockContext", + "description": [], + "signature": [ + "{}" + ], + "path": "packages/core/http/core-http-context-server-mocks/src/context_service.mock.ts", + "deprecated": false + } + ] + }, + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextServiceMock.createSetupContract", + "type": "Function", + "tags": [], + "label": "createSetupContract", + "description": [], + "signature": [ + "(mockContext?: {}) => jest.Mocked<", + "InternalContextSetup", + ">" + ], + "path": "packages/core/http/core-http-context-server-mocks/src/context_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-context-server-mocks", + "id": "def-server.contextServiceMock.createSetupContract.$1", + "type": "Object", + "tags": [], + "label": "mockContext", + "description": [], + "signature": [ + "{}" + ], + "path": "packages/core/http/core-http-context-server-mocks/src/context_service.mock.ts", + "deprecated": false + } + ] + } + ], + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx new file mode 100644 index 0000000000000..4eada9ea739b3 --- /dev/null +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -0,0 +1,30 @@ +--- +id: kibKbnCoreHttpContextServerMocksPluginApi +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 +summary: API docs for the @kbn/core-http-context-server-mocks plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] +warning: 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. +--- +import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 10 | 1 | 10 | 0 | + +## Server + +### Objects + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_http_router_server_internal.devdocs.json b/api_docs/kbn_core_http_router_server_internal.devdocs.json new file mode 100644 index 0000000000000..444c019edeea9 --- /dev/null +++ b/api_docs/kbn_core_http_router_server_internal.devdocs.json @@ -0,0 +1,414 @@ +{ + "id": "@kbn/core-http-router-server-internal", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.HapiResponseAdapter", + "type": "Class", + "tags": [], + "label": "HapiResponseAdapter", + "description": [], + "path": "packages/core/http/core-http-router-server-internal/src/response_adapter.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.HapiResponseAdapter.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response_adapter.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.HapiResponseAdapter.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "responseToolkit", + "description": [], + "signature": [ + "ResponseToolkit" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response_adapter.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.HapiResponseAdapter.toBadRequest", + "type": "Function", + "tags": [], + "label": "toBadRequest", + "description": [], + "signature": [ + "(message: string) => ", + "Boom", + "" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response_adapter.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.HapiResponseAdapter.toBadRequest.$1", + "type": "string", + "tags": [], + "label": "message", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response_adapter.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.HapiResponseAdapter.toInternalError", + "type": "Function", + "tags": [], + "label": "toInternalError", + "description": [], + "signature": [ + "() => ", + "Boom", + "" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response_adapter.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.HapiResponseAdapter.handle", + "type": "Function", + "tags": [], + "label": "handle", + "description": [], + "signature": [ + "(kibanaResponse: ", + "KibanaResponse", + ") => ", + "Boom", + " | ", + "ResponseObject" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response_adapter.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.HapiResponseAdapter.handle.$1", + "type": "Object", + "tags": [], + "label": "kibanaResponse", + "description": [], + "signature": [ + "KibanaResponse", + "" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response_adapter.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.filterHeaders", + "type": "Function", + "tags": [], + "label": "filterHeaders", + "description": [], + "signature": [ + "(headers: ", + "Headers", + ", fieldsToKeep: string[], fieldsToExclude: string[]) => ", + "Headers" + ], + "path": "packages/core/http/core-http-router-server-internal/src/headers.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.filterHeaders.$1", + "type": "CompoundType", + "tags": [], + "label": "headers", + "description": [], + "signature": [ + "Headers" + ], + "path": "packages/core/http/core-http-router-server-internal/src/headers.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.filterHeaders.$2", + "type": "Array", + "tags": [], + "label": "fieldsToKeep", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/core/http/core-http-router-server-internal/src/headers.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.filterHeaders.$3", + "type": "Array", + "tags": [], + "label": "fieldsToExclude", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/core/http/core-http-router-server-internal/src/headers.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.isKibanaResponse", + "type": "Function", + "tags": [], + "label": "isKibanaResponse", + "description": [], + "signature": [ + "(response: Record) => boolean" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.isKibanaResponse.$1", + "type": "Object", + "tags": [], + "label": "response", + "description": [], + "signature": [ + "Record" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.isSafeMethod", + "type": "Function", + "tags": [], + "label": "isSafeMethod", + "description": [], + "signature": [ + "(method: ", + "RouteMethod", + ") => boolean" + ], + "path": "packages/core/http/core-http-router-server-internal/src/route.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.isSafeMethod.$1", + "type": "CompoundType", + "tags": [], + "label": "method", + "description": [], + "signature": [ + "RouteMethod" + ], + "path": "packages/core/http/core-http-router-server-internal/src/route.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.kibanaResponseFactory", + "type": "Object", + "tags": [], + "label": "kibanaResponseFactory", + "description": [], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.kibanaResponseFactory.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.kibanaResponseFactory.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.kibanaResponseFactory.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.kibanaResponseFactory.custom", + "type": "Function", + "tags": [], + "label": "custom", + "description": [], + "signature": [ + " | Error | ", + "Stream", + " | Buffer | { message: string | Error; attributes?: ", + "ResponseErrorAttributes", + " | undefined; } | undefined>(options: ", + "CustomHttpResponseOptions", + ") => ", + "KibanaResponse", + "" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.kibanaResponseFactory.custom.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "CustomHttpResponseOptions", + "" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.lifecycleResponseFactory", + "type": "Object", + "tags": [], + "label": "lifecycleResponseFactory", + "description": [], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.lifecycleResponseFactory.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-router-server-internal", + "id": "def-server.lifecycleResponseFactory.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-router-server-internal/src/response.ts", + "deprecated": false + } + ], + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx new file mode 100644 index 0000000000000..1299925063937 --- /dev/null +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -0,0 +1,33 @@ +--- +id: kibKbnCoreHttpRouterServerInternalPluginApi +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 +summary: API docs for the @kbn/core-http-router-server-internal plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] +warning: 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. +--- +import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 25 | 5 | 25 | 1 | + +## Server + +### Objects + + +### Functions + + +### Classes + + diff --git a/api_docs/kbn_core_http_router_server_mocks.devdocs.json b/api_docs/kbn_core_http_router_server_mocks.devdocs.json new file mode 100644 index 0000000000000..90fbdecc75145 --- /dev/null +++ b/api_docs/kbn_core_http_router_server_mocks.devdocs.json @@ -0,0 +1,193 @@ +{ + "id": "@kbn/core-http-router-server-mocks", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-http-router-server-mocks", + "id": "def-server.RouterMock", + "type": "Type", + "tags": [], + "label": "RouterMock", + "description": [], + "signature": [ + "{ routerPath: string; get: jest.MockInstance, handler: ", + "RequestHandler", + "]>; post: jest.MockInstance, handler: ", + "RequestHandler", + "]>; put: jest.MockInstance, handler: ", + "RequestHandler", + "]>; patch: jest.MockInstance, handler: ", + "RequestHandler", + "]>; delete: jest.MockInstance, handler: ", + "RequestHandler", + "]>; handleLegacyErrors: jest.MockInstance<", + "RequestHandler", + ", [handler: ", + "RequestHandler", + "]>; getRoutes: jest.MockInstance<", + "RouterRoute", + "[], []>; } & ", + "IRouter", + "" + ], + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts", + "deprecated": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/core-http-router-server-mocks", + "id": "def-server.mockRouter", + "type": "Object", + "tags": [], + "label": "mockRouter", + "description": [], + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-mocks", + "id": "def-server.mockRouter.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "({ routerPath }?: { routerPath?: string | undefined; }) => ", + { + "pluginId": "@kbn/core-http-router-server-mocks", + "scope": "server", + "docId": "kibKbnCoreHttpRouterServerMocksPluginApi", + "section": "def-server.RouterMock", + "text": "RouterMock" + } + ], + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-mocks", + "id": "def-server.mockRouter.create.$1", + "type": "Object", + "tags": [], + "label": "__0", + "description": [], + "signature": [ + "{ routerPath?: string | undefined; }" + ], + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts", + "deprecated": false + } + ] + }, + { + "parentPluginId": "@kbn/core-http-router-server-mocks", + "id": "def-server.mockRouter.createKibanaRequest", + "type": "Function", + "tags": [], + "label": "createKibanaRequest", + "description": [], + "signature": [ + "

({ path, headers, params, body, query, method, socket, routeTags, routeAuthRequired, validation, kibanaRouteOptions, kibanaRequestState, auth, }?: ", + "RequestFixtureOptions", + ") => ", + "KibanaRequest", + "" + ], + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-router-server-mocks", + "id": "def-server.mockRouter.createKibanaRequest.$1", + "type": "Object", + "tags": [], + "label": "__0", + "description": [], + "signature": [ + "RequestFixtureOptions", + "" + ], + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts", + "deprecated": false + } + ] + }, + { + "parentPluginId": "@kbn/core-http-router-server-mocks", + "id": "def-server.mockRouter.createResponseFactory", + "type": "Function", + "tags": [], + "label": "createResponseFactory", + "description": [], + "signature": [ + "() => jest.Mocked<", + "KibanaResponseFactory", + ">" + ], + "path": "packages/core/http/core-http-router-server-mocks/src/router.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + } + ], + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx new file mode 100644 index 0000000000000..1d1b322e7eab1 --- /dev/null +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -0,0 +1,30 @@ +--- +id: kibKbnCoreHttpRouterServerMocksPluginApi +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 +summary: API docs for the @kbn/core-http-router-server-mocks plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] +warning: 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. +--- +import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 7 | 0 | 7 | 1 | + +## Server + +### Objects + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 80871a81a9d25..7194f634b2948 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-http-server plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] warning: 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. --- diff --git a/api_docs/kbn_core_http_server_internal.devdocs.json b/api_docs/kbn_core_http_server_internal.devdocs.json new file mode 100644 index 0000000000000..b0c482d9afc03 --- /dev/null +++ b/api_docs/kbn_core_http_server_internal.devdocs.json @@ -0,0 +1,845 @@ +{ + "id": "@kbn/core-http-server-internal", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.CspConfig", + "type": "Class", + "tags": [], + "label": "CspConfig", + "description": [ + "\nCSP configuration for use in Kibana." + ], + "signature": [ + { + "pluginId": "@kbn/core-http-server-internal", + "scope": "server", + "docId": "kibKbnCoreHttpServerInternalPluginApi", + "section": "def-server.CspConfig", + "text": "CspConfig" + }, + " implements ", + "ICspConfig" + ], + "path": "packages/core/http/core-http-server-internal/src/csp/csp_config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.CspConfig.DEFAULT", + "type": "Object", + "tags": [], + "label": "DEFAULT", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server-internal", + "scope": "server", + "docId": "kibKbnCoreHttpServerInternalPluginApi", + "section": "def-server.CspConfig", + "text": "CspConfig" + } + ], + "path": "packages/core/http/core-http-server-internal/src/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.CspConfig.directives", + "type": "Object", + "tags": [], + "label": "#directives", + "description": [], + "signature": [ + "CspDirectives" + ], + "path": "packages/core/http/core-http-server-internal/src/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.CspConfig.strict", + "type": "boolean", + "tags": [], + "label": "strict", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.CspConfig.warnLegacyBrowsers", + "type": "boolean", + "tags": [], + "label": "warnLegacyBrowsers", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.CspConfig.disableEmbedding", + "type": "boolean", + "tags": [], + "label": "disableEmbedding", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/csp/csp_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.CspConfig.header", + "type": "string", + "tags": [], + "label": "header", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/csp/csp_config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.ExternalUrlConfig", + "type": "Class", + "tags": [], + "label": "ExternalUrlConfig", + "description": [ + "\nExternal Url configuration for use in Kibana." + ], + "signature": [ + { + "pluginId": "@kbn/core-http-server-internal", + "scope": "server", + "docId": "kibKbnCoreHttpServerInternalPluginApi", + "section": "def-server.ExternalUrlConfig", + "text": "ExternalUrlConfig" + }, + " implements ", + "IExternalUrlConfig" + ], + "path": "packages/core/http/core-http-server-internal/src/external_url/external_url_config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.ExternalUrlConfig.DEFAULT", + "type": "Object", + "tags": [], + "label": "DEFAULT", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server-internal", + "scope": "server", + "docId": "kibKbnCoreHttpServerInternalPluginApi", + "section": "def-server.ExternalUrlConfig", + "text": "ExternalUrlConfig" + } + ], + "path": "packages/core/http/core-http-server-internal/src/external_url/external_url_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.ExternalUrlConfig.policy", + "type": "Array", + "tags": [], + "label": "policy", + "description": [], + "signature": [ + "IExternalUrlPolicy", + "[]" + ], + "path": "packages/core/http/core-http-server-internal/src/external_url/external_url_config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig", + "type": "Class", + "tags": [], + "label": "HttpConfig", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server-internal", + "scope": "server", + "docId": "kibKbnCoreHttpServerInternalPluginApi", + "section": "def-server.HttpConfig", + "text": "HttpConfig" + }, + " implements ", + "IHttpConfig" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.autoListen", + "type": "boolean", + "tags": [], + "label": "autoListen", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.host", + "type": "string", + "tags": [], + "label": "host", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.keepaliveTimeout", + "type": "number", + "tags": [], + "label": "keepaliveTimeout", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.socketTimeout", + "type": "number", + "tags": [], + "label": "socketTimeout", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.port", + "type": "number", + "tags": [], + "label": "port", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.cors", + "type": "Object", + "tags": [], + "label": "cors", + "description": [], + "signature": [ + "{ enabled: boolean; allowCredentials: boolean; allowOrigin: string[]; }" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.securityResponseHeaders", + "type": "Object", + "tags": [], + "label": "securityResponseHeaders", + "description": [], + "signature": [ + "{ [x: string]: string | string[]; }" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.customResponseHeaders", + "type": "Object", + "tags": [], + "label": "customResponseHeaders", + "description": [], + "signature": [ + "{ [x: string]: string | string[]; }" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.maxPayload", + "type": "Object", + "tags": [], + "label": "maxPayload", + "description": [], + "signature": [ + "ByteSizeValue" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.basePath", + "type": "string", + "tags": [], + "label": "basePath", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.publicBaseUrl", + "type": "string", + "tags": [], + "label": "publicBaseUrl", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.rewriteBasePath", + "type": "boolean", + "tags": [], + "label": "rewriteBasePath", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.ssl", + "type": "Object", + "tags": [], + "label": "ssl", + "description": [], + "signature": [ + "SslConfig" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.compression", + "type": "Object", + "tags": [], + "label": "compression", + "description": [], + "signature": [ + "{ enabled: boolean; referrerWhitelist?: string[] | undefined; }" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.csp", + "type": "Object", + "tags": [], + "label": "csp", + "description": [], + "signature": [ + "ICspConfig" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.externalUrl", + "type": "Object", + "tags": [], + "label": "externalUrl", + "description": [], + "signature": [ + "IExternalUrlConfig" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.xsrf", + "type": "Object", + "tags": [], + "label": "xsrf", + "description": [], + "signature": [ + "{ disableProtection: boolean; allowlist: string[]; }" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.requestId", + "type": "Object", + "tags": [], + "label": "requestId", + "description": [], + "signature": [ + "{ allowFromAnyIp: boolean; ipAllowlist: string[]; }" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfig.shutdownTimeout", + "type": "Object", + "tags": [], + "label": "shutdownTimeout", + "description": [], + "signature": [ + "moment.Duration" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer", + "type": "Class", + "tags": [], + "label": "HttpServer", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + "LoggerFactory" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.Unnamed.$2", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.Unnamed.$3", + "type": "Object", + "tags": [], + "label": "shutdownTimeout$", + "description": [], + "signature": [ + "Observable", + "" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.isListening", + "type": "Function", + "tags": [], + "label": "isListening", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.setup", + "type": "Function", + "tags": [], + "label": "setup", + "description": [], + "signature": [ + "(config: ", + { + "pluginId": "@kbn/core-http-server-internal", + "scope": "server", + "docId": "kibKbnCoreHttpServerInternalPluginApi", + "section": "def-server.HttpConfig", + "text": "HttpConfig" + }, + ", executionContext?: ", + "IExecutionContext", + " | undefined) => Promise<", + "HttpServerSetup", + ">" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.setup.$1", + "type": "Object", + "tags": [], + "label": "config", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-server-internal", + "scope": "server", + "docId": "kibKbnCoreHttpServerInternalPluginApi", + "section": "def-server.HttpConfig", + "text": "HttpConfig" + } + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.setup.$2", + "type": "Object", + "tags": [], + "label": "executionContext", + "description": [], + "signature": [ + "IExecutionContext", + " | undefined" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.start", + "type": "Function", + "tags": [], + "label": "start", + "description": [], + "signature": [ + "() => Promise" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpServer.stop", + "type": "Function", + "tags": [], + "label": "stop", + "description": [], + "signature": [ + "() => Promise" + ], + "path": "packages/core/http/core-http-server-internal/src/http_server.ts", + "deprecated": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.createCookieSessionStorageFactory", + "type": "Function", + "tags": [], + "label": "createCookieSessionStorageFactory", + "description": [ + "\nCreates SessionStorage factory, which abstract the way of\nsession storage implementation and scoping to the incoming requests.\n" + ], + "signature": [ + "(log: ", + "Logger", + ", server: ", + "Server", + ", cookieOptions: ", + "SessionStorageCookieOptions", + ", basePath: string | undefined) => Promise<", + "SessionStorageFactory", + ">" + ], + "path": "packages/core/http/core-http-server-internal/src/cookie_session_storage.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.createCookieSessionStorageFactory.$1", + "type": "Object", + "tags": [], + "label": "log", + "description": [], + "signature": [ + "Logger" + ], + "path": "packages/core/http/core-http-server-internal/src/cookie_session_storage.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.createCookieSessionStorageFactory.$2", + "type": "Object", + "tags": [], + "label": "server", + "description": [ + "- hapi server to create SessionStorage for" + ], + "signature": [ + "Server" + ], + "path": "packages/core/http/core-http-server-internal/src/cookie_session_storage.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.createCookieSessionStorageFactory.$3", + "type": "Object", + "tags": [], + "label": "cookieOptions", + "description": [ + "- cookies configuration" + ], + "signature": [ + "SessionStorageCookieOptions", + "" + ], + "path": "packages/core/http/core-http-server-internal/src/cookie_session_storage.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.createCookieSessionStorageFactory.$4", + "type": "string", + "tags": [], + "label": "basePath", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/core/http/core-http-server-internal/src/cookie_session_storage.ts", + "deprecated": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.HttpConfigType", + "type": "Type", + "tags": [], + "label": "HttpConfigType", + "description": [], + "signature": [ + "{ readonly basePath?: string | undefined; readonly uuid?: string | undefined; readonly publicBaseUrl?: string | undefined; readonly name: string; 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: \"none\" | \"required\" | \"optional\"; }>; readonly host: string; readonly port: number; readonly compression: Readonly<{ referrerWhitelist?: string[] | undefined; } & { enabled: boolean; }>; 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: ", + "ByteSizeValue", + "; readonly rewriteBasePath: boolean; readonly keepaliveTimeout: number; readonly socketTimeout: number; readonly xsrf: Readonly<{} & { disableProtection: boolean; allowlist: string[]; }>; readonly requestId: Readonly<{} & { allowFromAnyIp: boolean; ipAllowlist: string[]; }>; }" + ], + "path": "packages/core/http/core-http-server-internal/src/http_config.ts", + "deprecated": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.cspConfig", + "type": "Object", + "tags": [], + "label": "cspConfig", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/csp/config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.cspConfig.path", + "type": "string", + "tags": [], + "label": "path", + "description": [ + "// TODO: Move this to server.csp using config deprecations\n// ? https://github.com/elastic/kibana/pull/52251" + ], + "path": "packages/core/http/core-http-server-internal/src/csp/config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.cspConfig.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [], + "signature": [ + "ObjectType", + "<{ disableUnsafeEval: ", + "ConditionalType", + "; script_src: ", + "Type", + "; worker_src: ", + "Type", + "; style_src: ", + "Type", + "; connect_src: ", + "Type", + "; default_src: ", + "Type", + "; font_src: ", + "Type", + "; frame_src: ", + "Type", + "; img_src: ", + "Type", + "; frame_ancestors: ", + "Type", + "; report_uri: ", + "Type", + "; report_to: ", + "Type", + "; strict: ", + "Type", + "; warnLegacyBrowsers: ", + "Type", + "; disableEmbedding: ", + "Type", + "; }>" + ], + "path": "packages/core/http/core-http-server-internal/src/csp/config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.externalUrlConfig", + "type": "Object", + "tags": [], + "label": "externalUrlConfig", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/external_url/config.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.externalUrlConfig.path", + "type": "string", + "tags": [], + "label": "path", + "description": [], + "path": "packages/core/http/core-http-server-internal/src/external_url/config.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-internal", + "id": "def-server.externalUrlConfig.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [], + "signature": [ + "ObjectType", + "<{ policy: ", + "Type", + "<", + "IExternalUrlPolicy", + "[]>; }>" + ], + "path": "packages/core/http/core-http-server-internal/src/external_url/config.ts", + "deprecated": false + } + ], + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx new file mode 100644 index 0000000000000..995891f2568ff --- /dev/null +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -0,0 +1,36 @@ +--- +id: kibKbnCoreHttpServerInternalPluginApi +slug: /kibana-dev-docs/api/kbn-core-http-server-internal +title: "@kbn/core-http-server-internal" +image: https://source.unsplash.com/400x175/?github +summary: API docs for the @kbn/core-http-server-internal plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] +warning: 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. +--- +import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 54 | 0 | 48 | 2 | + +## Server + +### Objects + + +### Functions + + +### Classes + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_http_server_mocks.devdocs.json b/api_docs/kbn_core_http_server_mocks.devdocs.json new file mode 100644 index 0000000000000..bdbc8ce677929 --- /dev/null +++ b/api_docs/kbn_core_http_server_mocks.devdocs.json @@ -0,0 +1,830 @@ +{ + "id": "@kbn/core-http-server-mocks", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.createCoreContext", + "type": "Function", + "tags": [], + "label": "createCoreContext", + "description": [], + "signature": [ + "(overrides?: Partial<", + "CoreContext", + ">) => ", + "CoreContext" + ], + "path": "packages/core/http/core-http-server-mocks/src/test_utils.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.createCoreContext.$1", + "type": "Object", + "tags": [], + "label": "overrides", + "description": [], + "signature": [ + "Partial<", + "CoreContext", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/test_utils.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.createHttpServer", + "type": "Function", + "tags": [], + "label": "createHttpServer", + "description": [ + "\nCreates a concrete HttpServer with a mocked context." + ], + "signature": [ + "(overrides?: Partial<", + "CoreContext", + ">) => ", + "HttpService" + ], + "path": "packages/core/http/core-http-server-mocks/src/test_utils.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.createHttpServer.$1", + "type": "Object", + "tags": [], + "label": "overrides", + "description": [], + "signature": [ + "Partial<", + "CoreContext", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/test_utils.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.HttpServicePrebootMock", + "type": "Type", + "tags": [], + "label": "HttpServicePrebootMock", + "description": [], + "signature": [ + "{ registerRoutes: jest.MockInstance) => void]>; basePath: ", + "IBasePath", + "; getServerInfo: jest.MockInstance<", + "HttpServerInfo", + ", []>; } & ", + "HttpServicePreboot", + "<", + "RequestHandlerContextBase", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.HttpServiceSetupMock", + "type": "Type", + "tags": [], + "label": "HttpServiceSetupMock", + "description": [], + "signature": [ + "{ csp: ", + "ICspConfig", + "; createCookieSessionStorageFactory: jest.MockInstance>, [cookieOptions: ", + "SessionStorageCookieOptions", + "]>; registerOnPreRouting: jest.MockInstance; registerOnPreAuth: jest.MockInstance; registerAuth: jest.MockInstance; registerOnPostAuth: jest.MockInstance; registerOnPreResponse: jest.MockInstance; getServerInfo: jest.MockInstance<", + "HttpServerInfo", + ", []>; registerRouteHandlerContext: jest.MockInstance<", + "IContextContainer", + ", [contextName: Exclude, provider: ", + "IContextProvider", + ">]>; } & Omit<", + "HttpServiceSetup", + ", \"basePath\" | \"createRouter\"> & { basePath: BasePathMocked; createRouter: jest.MockedFunction<() => ", + "RouterMock", + ">; }" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.HttpServiceStartMock", + "type": "Type", + "tags": [], + "label": "HttpServiceStartMock", + "description": [], + "signature": [ + "{ basePath: ", + "IBasePath", + "; auth: ", + "HttpAuth", + "; getServerInfo: jest.MockInstance<", + "HttpServerInfo", + ", []>; } & ", + "HttpServiceStart", + " & { basePath: BasePathMocked; }" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.InternalHttpServicePrebootMock", + "type": "Type", + "tags": [], + "label": "InternalHttpServicePrebootMock", + "description": [], + "signature": [ + "{ auth: ", + "HttpAuth", + "; server: ", + "Server", + "; externalUrl: ", + "ExternalUrlConfig", + "; csp: ", + "ICspConfig", + "; registerStaticDir: jest.MockInstance; getServerInfo: jest.MockInstance<", + "HttpServerInfo", + ", []>; registerRouteHandlerContext: jest.MockInstance]>; registerRoutes: jest.MockInstance) => void]>; } & Omit<", + "InternalHttpServicePreboot", + ", \"basePath\"> & { basePath: BasePathMocked; }" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.InternalHttpServiceSetupMock", + "type": "Type", + "tags": [], + "label": "InternalHttpServiceSetupMock", + "description": [], + "signature": [ + "{ server: ", + "Server", + "; externalUrl: ", + "ExternalUrlConfig", + "; csp: ", + "ICspConfig", + "; registerRouterAfterListening: jest.MockInstance]>; registerStaticDir: jest.MockInstance; createCookieSessionStorageFactory: jest.MockInstance>, [cookieOptions: ", + "SessionStorageCookieOptions", + "]>; registerOnPreRouting: jest.MockInstance; registerOnPreAuth: jest.MockInstance; registerAuth: jest.MockInstance; registerOnPostAuth: jest.MockInstance; registerOnPreResponse: jest.MockInstance; getServerInfo: jest.MockInstance<", + "HttpServerInfo", + ", []>; registerRouteHandlerContext: jest.MockInstance]>; registerPrebootRoutes: jest.MockInstance) => void]>; } & Omit<", + "InternalHttpServiceSetup", + ", \"basePath\" | \"auth\" | \"authRequestHeaders\" | \"createRouter\"> & { auth: AuthMocked; basePath: BasePathMocked; createRouter: jest.MockedFunction<(path: string) => ", + "RouterMock", + ">; authRequestHeaders: jest.Mocked<", + "IAuthHeadersStorage", + ">; }" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.InternalHttpServiceStartMock", + "type": "Type", + "tags": [], + "label": "InternalHttpServiceStartMock", + "description": [], + "signature": [ + "{ isListening: jest.MockInstance; basePath: ", + "IBasePath", + "; auth: ", + "HttpAuth", + "; getServerInfo: jest.MockInstance<", + "HttpServerInfo", + ", []>; } & ", + "InternalHttpServiceStart", + " & { basePath: BasePathMocked; }" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServerMock", + "type": "Object", + "tags": [], + "label": "httpServerMock", + "description": [], + "path": "packages/core/http/core-http-server-mocks/src/http_server.mocks.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServerMock.createKibanaRequest", + "type": "Function", + "tags": [], + "label": "createKibanaRequest", + "description": [], + "signature": [ + "

({ path, headers, params, body, query, method, socket, routeTags, routeAuthRequired, validation, kibanaRouteOptions, kibanaRequestState, auth, }?: ", + "RequestFixtureOptions", + " | undefined) => ", + "KibanaRequest", + "" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_server.mocks.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServerMock.createKibanaRequest.$1", + "type": "Object", + "tags": [], + "label": "__0", + "description": [], + "signature": [ + "RequestFixtureOptions", + " | undefined" + ], + "path": "node_modules/@types/kbn__core-http-router-server-mocks/index.d.ts", + "deprecated": false + } + ] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServerMock.createRawRequest", + "type": "Function", + "tags": [], + "label": "createRawRequest", + "description": [], + "signature": [ + "(customization?: ", + "DeepPartialObject", + "<", + "Request", + "> | undefined) => ", + "Request" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_server.mocks.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServerMock.createRawRequest.$1", + "type": "Object", + "tags": [], + "label": "customization", + "description": [], + "signature": [ + "DeepPartialObject", + "<", + "Request", + "> | undefined" + ], + "path": "node_modules/@types/kbn__hapi-mocks/index.d.ts", + "deprecated": false + } + ] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServerMock.createResponseFactory", + "type": "Function", + "tags": [], + "label": "createResponseFactory", + "description": [], + "signature": [ + "() => jest.Mocked<", + "KibanaResponseFactory", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_server.mocks.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServerMock.createLifecycleResponseFactory", + "type": "Function", + "tags": [], + "label": "createLifecycleResponseFactory", + "description": [], + "signature": [ + "() => jest.Mocked<", + "LifecycleResponseFactory", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_server.mocks.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServerMock.createToolkit", + "type": "Function", + "tags": [], + "label": "createToolkit", + "description": [], + "signature": [ + "() => ToolkitMock" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_server.mocks.ts", + "deprecated": false, + "returnComment": [], + "children": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock", + "type": "Object", + "tags": [], + "label": "httpServiceMock", + "description": [], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "() => jest.Mocked" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createBasePath", + "type": "Function", + "tags": [], + "label": "createBasePath", + "description": [], + "signature": [ + "(serverBasePath?: string, publicBaseUrl?: string) => BasePathMocked" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createBasePath.$1", + "type": "string", + "tags": [], + "label": "serverBasePath", + "description": [], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createBasePath.$2", + "type": "string", + "tags": [], + "label": "publicBaseUrl", + "description": [], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false + } + ] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createAuth", + "type": "Function", + "tags": [], + "label": "createAuth", + "description": [], + "signature": [ + "() => AuthMocked" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createInternalPrebootContract", + "type": "Function", + "tags": [], + "label": "createInternalPrebootContract", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/core-http-server-mocks", + "scope": "server", + "docId": "kibKbnCoreHttpServerMocksPluginApi", + "section": "def-server.InternalHttpServicePrebootMock", + "text": "InternalHttpServicePrebootMock" + } + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createPrebootContract", + "type": "Function", + "tags": [], + "label": "createPrebootContract", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/core-http-server-mocks", + "scope": "server", + "docId": "kibKbnCoreHttpServerMocksPluginApi", + "section": "def-server.HttpServicePrebootMock", + "text": "HttpServicePrebootMock" + } + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createInternalSetupContract", + "type": "Function", + "tags": [], + "label": "createInternalSetupContract", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/core-http-server-mocks", + "scope": "server", + "docId": "kibKbnCoreHttpServerMocksPluginApi", + "section": "def-server.InternalHttpServiceSetupMock", + "text": "InternalHttpServiceSetupMock" + } + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createSetupContract", + "type": "Function", + "tags": [], + "label": "createSetupContract", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/core-http-server-mocks", + "scope": "server", + "docId": "kibKbnCoreHttpServerMocksPluginApi", + "section": "def-server.HttpServiceSetupMock", + "text": "HttpServiceSetupMock" + }, + "" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createInternalStartContract", + "type": "Function", + "tags": [], + "label": "createInternalStartContract", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/core-http-server-mocks", + "scope": "server", + "docId": "kibKbnCoreHttpServerMocksPluginApi", + "section": "def-server.InternalHttpServiceStartMock", + "text": "InternalHttpServiceStartMock" + } + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createStartContract", + "type": "Function", + "tags": [], + "label": "createStartContract", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/core-http-server-mocks", + "scope": "server", + "docId": "kibKbnCoreHttpServerMocksPluginApi", + "section": "def-server.HttpServiceStartMock", + "text": "HttpServiceStartMock" + } + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createOnPreAuthToolkit", + "type": "Function", + "tags": [], + "label": "createOnPreAuthToolkit", + "description": [], + "signature": [ + "() => jest.Mocked<", + "OnPreAuthToolkit", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createOnPostAuthToolkit", + "type": "Function", + "tags": [], + "label": "createOnPostAuthToolkit", + "description": [], + "signature": [ + "() => jest.Mocked<", + "OnPostAuthToolkit", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createOnPreResponseToolkit", + "type": "Function", + "tags": [], + "label": "createOnPreResponseToolkit", + "description": [], + "signature": [ + "() => jest.Mocked<", + "OnPreResponseToolkit", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createOnPreRoutingToolkit", + "type": "Function", + "tags": [], + "label": "createOnPreRoutingToolkit", + "description": [], + "signature": [ + "() => jest.Mocked<", + "OnPreRoutingToolkit", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createAuthToolkit", + "type": "Function", + "tags": [], + "label": "createAuthToolkit", + "description": [], + "signature": [ + "() => jest.Mocked<", + "AuthToolkit", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createAuthHeaderStorage", + "type": "Function", + "tags": [], + "label": "createAuthHeaderStorage", + "description": [], + "signature": [ + "() => jest.Mocked<", + "IAuthHeadersStorage", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createRouter", + "type": "Function", + "tags": [], + "label": "createRouter", + "description": [], + "signature": [ + "({ routerPath }?: { routerPath?: string | undefined; } | undefined) => ", + "RouterMock" + ], + "path": "packages/core/http/core-http-server-mocks/src/http_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.httpServiceMock.createRouter.$1", + "type": "Object", + "tags": [], + "label": "__0", + "description": [], + "signature": [ + "{ routerPath?: string | undefined; } | undefined" + ], + "path": "node_modules/@types/kbn__core-http-router-server-mocks/index.d.ts", + "deprecated": false + } + ] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.sessionStorageMock", + "type": "Object", + "tags": [], + "label": "sessionStorageMock", + "description": [], + "path": "packages/core/http/core-http-server-mocks/src/cookie_session_storage.mocks.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.sessionStorageMock.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "() => jest.Mocked<", + "SessionStorage", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/cookie_session_storage.mocks.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-http-server-mocks", + "id": "def-server.sessionStorageMock.createFactory", + "type": "Function", + "tags": [], + "label": "createFactory", + "description": [], + "signature": [ + "() => DeepMocked<", + "SessionStorageFactory", + ">" + ], + "path": "packages/core/http/core-http-server-mocks/src/cookie_session_storage.mocks.ts", + "deprecated": false, + "returnComment": [], + "children": [] + } + ], + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx new file mode 100644 index 0000000000000..404234635c958 --- /dev/null +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -0,0 +1,33 @@ +--- +id: kibKbnCoreHttpServerMocksPluginApi +slug: /kibana-dev-docs/api/kbn-core-http-server-mocks +title: "@kbn/core-http-server-mocks" +image: https://source.unsplash.com/400x175/?github +summary: API docs for the @kbn/core-http-server-mocks plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] +warning: 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. +--- +import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 41 | 0 | 37 | 0 | + +## Server + +### Objects + + +### Functions + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index fd5dc5578ec45..895827b42752c 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-i18n-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] warning: 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. --- diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 451a717d03e00..82b3437b0381f 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index e1277bff51595..c7da5326fe12f 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] warning: 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. --- diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 315b6ccb8dd93..42994d0e6dff9 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 1e2f604a6658a..c0429e0c27529 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-logging-server plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] warning: 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. --- diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 6c2e940096f8a..05371a5d2e267 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 41a4a645ccbb6..cd247288d21b0 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 1b2f3c80de467..07db2e25dbfa6 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-node-server plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] warning: 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. --- diff --git a/api_docs/kbn_core_node_server_internal.devdocs.json b/api_docs/kbn_core_node_server_internal.devdocs.json index 1937ba5e72c7d..0e598b07cd930 100644 --- a/api_docs/kbn_core_node_server_internal.devdocs.json +++ b/api_docs/kbn_core_node_server_internal.devdocs.json @@ -49,7 +49,7 @@ "ObjectType", "<{ roles: ", "Type", - "<(\"ui\" | \"background_tasks\")[] | \"*\"[]>; }>" + "<\"*\"[] | (\"ui\" | \"background_tasks\")[]>; }>" ], "path": "packages/core/node/core-node-server-internal/src/node_config.ts", "deprecated": false diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 5885b29b2c8c8..67b704d71fa4e 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-node-server-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 9e667be321173..177cb534f5c22 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index b109431d1dbad..4710e583c5929 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-preboot-server plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] warning: 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. --- diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index ed3173fb57216..4089f2b7c921a 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.devdocs.json b/api_docs/kbn_core_test_helpers_http_setup_browser.devdocs.json new file mode 100644 index 0000000000000..477484917583d --- /dev/null +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.devdocs.json @@ -0,0 +1,141 @@ +{ + "id": "@kbn/core-test-helpers-http-setup-browser", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/core-test-helpers-http-setup-browser", + "id": "def-common.setup", + "type": "Function", + "tags": [], + "label": "setup", + "description": [], + "signature": [ + "(tap: ", + { + "pluginId": "@kbn/core-test-helpers-http-setup-browser", + "scope": "common", + "docId": "kibKbnCoreTestHelpersHttpSetupBrowserPluginApi", + "section": "def-common.SetupTap", + "text": "SetupTap" + }, + ") => { httpService: ", + "HttpService", + "; injectedMetadata: jest.Mocked<", + "InternalInjectedMetadataSetup", + ">; fatalErrors: jest.Mocked<", + "FatalErrorsSetup", + ">; http: ", + "HttpSetup", + "; }" + ], + "path": "packages/core/test-helpers/core-test-helpers-http-setup-browser/src/http_test_setup.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-test-helpers-http-setup-browser", + "id": "def-common.setup.$1", + "type": "Function", + "tags": [], + "label": "tap", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-test-helpers-http-setup-browser", + "scope": "common", + "docId": "kibKbnCoreTestHelpersHttpSetupBrowserPluginApi", + "section": "def-common.SetupTap", + "text": "SetupTap" + } + ], + "path": "packages/core/test-helpers/core-test-helpers-http-setup-browser/src/http_test_setup.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-test-helpers-http-setup-browser", + "id": "def-common.SetupTap", + "type": "Type", + "tags": [], + "label": "SetupTap", + "description": [], + "signature": [ + "(injectedMetadata: jest.Mocked<", + "InternalInjectedMetadataSetup", + ">, fatalErrors: jest.Mocked<", + "FatalErrorsSetup", + ">) => void" + ], + "path": "packages/core/test-helpers/core-test-helpers-http-setup-browser/src/http_test_setup.ts", + "deprecated": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/core-test-helpers-http-setup-browser", + "id": "def-common.SetupTap.$1", + "type": "CompoundType", + "tags": [], + "label": "injectedMetadata", + "description": [], + "signature": [ + "{ getBasePath: jest.MockInstance; getServerBasePath: jest.MockInstance; getPublicBaseUrl: jest.MockInstance; getKibanaBuildNumber: jest.MockInstance; getKibanaBranch: jest.MockInstance; getKibanaVersion: jest.MockInstance; getCspConfig: jest.MockInstance<{ warnLegacyBrowsers: boolean; }, []>; getExternalUrlConfig: jest.MockInstance<{ policy: ", + "InjectedMetadataExternalUrlPolicy", + "[]; }, []>; getTheme: jest.MockInstance<{ darkMode: boolean; version: \"v8\"; }, []>; getElasticsearchInfo: jest.MockInstance<", + "InjectedMetadataClusterInfo", + ", []>; getPlugins: jest.MockInstance<", + "InjectedMetadataPlugin", + "[], []>; getAnonymousStatusPage: jest.MockInstance; getLegacyMetadata: jest.MockInstance<{ uiSettings: { defaults: Record; user?: Record | undefined; }; }, []>; getInjectedVar: jest.MockInstance; getInjectedVars: jest.MockInstance<{ [key: string]: unknown; }, []>; } & ", + "InternalInjectedMetadataSetup" + ], + "path": "packages/core/test-helpers/core-test-helpers-http-setup-browser/src/http_test_setup.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-test-helpers-http-setup-browser", + "id": "def-common.SetupTap.$2", + "type": "CompoundType", + "tags": [], + "label": "fatalErrors", + "description": [], + "signature": [ + "{ add: jest.MockInstance; get$: jest.MockInstance<", + "Observable", + "<", + "FatalErrorInfo", + ">, []>; } & ", + "FatalErrorsSetup" + ], + "path": "packages/core/test-helpers/core-test-helpers-http-setup-browser/src/http_test_setup.ts", + "deprecated": false + } + ], + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx new file mode 100644 index 0000000000000..6ac099e4d0c26 --- /dev/null +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -0,0 +1,30 @@ +--- +id: kibKbnCoreTestHelpersHttpSetupBrowserPluginApi +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 +summary: API docs for the @kbn/core-test-helpers-http-setup-browser plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] +warning: 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. +--- +import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.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 | 5 | 0 | + +## Common + +### Functions + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 09957ca3e6854..4ff5ac041bbd6 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-theme-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] warning: 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. --- diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index c3a60618f7845..d9030c96ae6ed 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] warning: 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. --- diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 3a7174fc1b2e3..1c0a9295e2d8c 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] warning: 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. --- diff --git a/api_docs/kbn_core_ui_settings_browser.devdocs.json b/api_docs/kbn_core_ui_settings_browser.devdocs.json new file mode 100644 index 0000000000000..20f23615866bd --- /dev/null +++ b/api_docs/kbn_core_ui_settings_browser.devdocs.json @@ -0,0 +1,432 @@ +{ + "id": "@kbn/core-ui-settings-browser", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient", + "type": "Interface", + "tags": [], + "label": "IUiSettingsClient", + "description": [ + "\nClient-side client that provides access to the advanced settings stored in elasticsearch.\nThe settings provide control over the behavior of the Kibana application.\nFor example, a user can specify how to display numeric or date fields.\nUsers can adjust the settings via Management UI.\n{@link IUiSettingsClient}\n" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.get", + "type": "Function", + "tags": [], + "label": "get", + "description": [ + "\nGets the value for a specific uiSetting. If this setting has no user-defined value\nthen the `defaultOverride` parameter is returned (and parsed if setting is of type\n\"json\" or \"number). If the parameter is not defined and the key is not registered\nby any plugin then an error is thrown, otherwise reads the default value defined by a plugin." + ], + "signature": [ + "(key: string, defaultOverride?: T | undefined) => T" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.get.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.get.$2", + "type": "Uncategorized", + "tags": [], + "label": "defaultOverride", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.get$", + "type": "Function", + "tags": [], + "label": "get$", + "description": [ + "\nGets an observable of the current value for a config key, and all updates to that config\nkey in the future. Providing a `defaultOverride` argument behaves the same as it does in #get()" + ], + "signature": [ + "(key: string, defaultOverride?: T | undefined) => ", + "Observable", + "" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.get$.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.get$.$2", + "type": "Uncategorized", + "tags": [], + "label": "defaultOverride", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.getAll", + "type": "Function", + "tags": [], + "label": "getAll", + "description": [ + "\nGets the metadata about all uiSettings, including the type, default value, and user value\nfor each key." + ], + "signature": [ + "() => Readonly>>" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.set", + "type": "Function", + "tags": [], + "label": "set", + "description": [ + "\nSets the value for a uiSetting. If the setting is not registered by any plugin\nit will be stored as a custom setting. The new value will be synchronously available via\nthe `get()` method and sent to the server in the background. If the request to the\nserver fails then a updateErrors$ will be notified and the setting will be\nreverted to its value before `set()` was called." + ], + "signature": [ + "(key: string, value: any) => Promise" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.set.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.set.$2", + "type": "Any", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.remove", + "type": "Function", + "tags": [], + "label": "remove", + "description": [ + "\nRemoves the user-defined value for a setting, causing it to revert to the default. This\nmethod behaves the same as calling `set(key, null)`, including the synchronization, custom\nsetting, and error behavior of that method." + ], + "signature": [ + "(key: string) => Promise" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.remove.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.isDeclared", + "type": "Function", + "tags": [], + "label": "isDeclared", + "description": [ + "\nReturns true if the key is a \"known\" uiSetting, meaning it is either registered\nby any plugin or was previously added as a custom setting via the `set()` method." + ], + "signature": [ + "(key: string) => boolean" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.isDeclared.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.isDefault", + "type": "Function", + "tags": [], + "label": "isDefault", + "description": [ + "\nReturns true if the setting has no user-defined value or is unknown" + ], + "signature": [ + "(key: string) => boolean" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.isDefault.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.isCustom", + "type": "Function", + "tags": [], + "label": "isCustom", + "description": [ + "\nReturns true if the setting wasn't registered by any plugin, but was either\nadded directly via `set()`, or is an unknown setting found in the uiSettings saved\nobject" + ], + "signature": [ + "(key: string) => boolean" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.isCustom.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.isOverridden", + "type": "Function", + "tags": [], + "label": "isOverridden", + "description": [ + "\nShows whether the uiSettings value set by the user." + ], + "signature": [ + "(key: string) => boolean" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.isOverridden.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.getUpdate$", + "type": "Function", + "tags": [], + "label": "getUpdate$", + "description": [ + "\nReturns an Observable that notifies subscribers of each update to the uiSettings,\nincluding the key, newValue, and oldValue of the setting that changed." + ], + "signature": [ + "() => ", + "Observable", + "<{ key: string; newValue: T; oldValue: T; }>" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.IUiSettingsClient.getUpdateErrors$", + "type": "Function", + "tags": [], + "label": "getUpdateErrors$", + "description": [ + "\nReturns an Observable that notifies subscribers of each error while trying to update\nthe settings, containing the actual Error class." + ], + "signature": [ + "() => ", + "Observable", + "" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.UiSettingsState", + "type": "Interface", + "tags": [], + "label": "UiSettingsState", + "description": [], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser", + "id": "def-common.UiSettingsState.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[key: string]: PublicUiSettingsParams & UserProvidedValues", + "description": [], + "signature": [ + "[key: string]: ", + "PublicUiSettingsParams", + " & ", + "UserProvidedValues", + "" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser/src/types.ts", + "deprecated": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx new file mode 100644 index 0000000000000..a4ad1186579de --- /dev/null +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -0,0 +1,27 @@ +--- +id: kibKbnCoreUiSettingsBrowserPluginApi +slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser +title: "@kbn/core-ui-settings-browser" +image: https://source.unsplash.com/400x175/?github +summary: API docs for the @kbn/core-ui-settings-browser plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] +warning: 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. +--- +import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 25 | 1 | 13 | 0 | + +## Common + +### Interfaces + + diff --git a/api_docs/kbn_core_ui_settings_browser_internal.devdocs.json b/api_docs/kbn_core_ui_settings_browser_internal.devdocs.json new file mode 100644 index 0000000000000..3bf2fabb7e222 --- /dev/null +++ b/api_docs/kbn_core_ui_settings_browser_internal.devdocs.json @@ -0,0 +1,419 @@ +{ + "id": "@kbn/core-ui-settings-browser-internal", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient", + "type": "Class", + "tags": [], + "label": "UiSettingsClient", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-ui-settings-browser-internal", + "scope": "common", + "docId": "kibKbnCoreUiSettingsBrowserInternalPluginApi", + "section": "def-common.UiSettingsClient", + "text": "UiSettingsClient" + }, + " implements ", + "IUiSettingsClient" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "params", + "description": [], + "signature": [ + "UiSettingsClientParams" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.getAll", + "type": "Function", + "tags": [], + "label": "getAll", + "description": [], + "signature": [ + "() => Record>" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.get", + "type": "Function", + "tags": [], + "label": "get", + "description": [], + "signature": [ + "(key: string, defaultOverride?: T | undefined) => any" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.get.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.get.$2", + "type": "Uncategorized", + "tags": [], + "label": "defaultOverride", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.get$", + "type": "Function", + "tags": [], + "label": "get$", + "description": [], + "signature": [ + "(key: string, defaultOverride?: T | undefined) => ", + "Observable", + "" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.get$.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.get$.$2", + "type": "Uncategorized", + "tags": [], + "label": "defaultOverride", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.set", + "type": "Function", + "tags": [], + "label": "set", + "description": [], + "signature": [ + "(key: string, value: any) => Promise" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.set.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.set.$2", + "type": "Any", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.remove", + "type": "Function", + "tags": [], + "label": "remove", + "description": [], + "signature": [ + "(key: string) => Promise" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.remove.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.isDeclared", + "type": "Function", + "tags": [], + "label": "isDeclared", + "description": [], + "signature": [ + "(key: string) => boolean" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.isDeclared.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.isDefault", + "type": "Function", + "tags": [], + "label": "isDefault", + "description": [], + "signature": [ + "(key: string) => boolean" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.isDefault.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.isCustom", + "type": "Function", + "tags": [], + "label": "isCustom", + "description": [], + "signature": [ + "(key: string) => boolean" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.isCustom.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.isOverridden", + "type": "Function", + "tags": [], + "label": "isOverridden", + "description": [], + "signature": [ + "(key: string) => boolean" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.isOverridden.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.getUpdate$", + "type": "Function", + "tags": [], + "label": "getUpdate$", + "description": [], + "signature": [ + "() => ", + "Observable", + "<{ key: string; newValue: any; oldValue: any; }>" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-internal", + "id": "def-common.UiSettingsClient.getUpdateErrors$", + "type": "Function", + "tags": [], + "label": "getUpdateErrors$", + "description": [], + "signature": [ + "() => ", + "Observable", + "" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts", + "deprecated": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx new file mode 100644 index 0000000000000..42b710a0fb9fa --- /dev/null +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -0,0 +1,27 @@ +--- +id: kibKbnCoreUiSettingsBrowserInternalPluginApi +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 +summary: API docs for the @kbn/core-ui-settings-browser-internal plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] +warning: 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. +--- +import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 25 | 1 | 25 | 0 | + +## Common + +### Classes + + diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.devdocs.json b/api_docs/kbn_core_ui_settings_browser_mocks.devdocs.json new file mode 100644 index 0000000000000..c836e521e1e16 --- /dev/null +++ b/api_docs/kbn_core_ui_settings_browser_mocks.devdocs.json @@ -0,0 +1,90 @@ +{ + "id": "@kbn/core-ui-settings-browser-mocks", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-mocks", + "id": "def-common.uiSettingsServiceMock", + "type": "Object", + "tags": [], + "label": "uiSettingsServiceMock", + "description": [], + "path": "packages/core/ui-settings/core-ui-settings-browser-mocks/src/ui_settings_service.mock.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-browser-mocks", + "id": "def-common.uiSettingsServiceMock.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "() => jest.Mocked" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-mocks/src/ui_settings_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-mocks", + "id": "def-common.uiSettingsServiceMock.createSetupContract", + "type": "Function", + "tags": [], + "label": "createSetupContract", + "description": [], + "signature": [ + "() => jest.Mocked<", + "IUiSettingsClient", + ">" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-mocks/src/ui_settings_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-ui-settings-browser-mocks", + "id": "def-common.uiSettingsServiceMock.createStartContract", + "type": "Function", + "tags": [], + "label": "createStartContract", + "description": [], + "signature": [ + "() => jest.Mocked<", + "IUiSettingsClient", + ">" + ], + "path": "packages/core/ui-settings/core-ui-settings-browser-mocks/src/ui_settings_service.mock.ts", + "deprecated": false, + "returnComment": [], + "children": [] + } + ], + "initialIsOpen": false + } + ] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx new file mode 100644 index 0000000000000..ed65b843361f2 --- /dev/null +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -0,0 +1,27 @@ +--- +id: kibKbnCoreUiSettingsBrowserMocksPluginApi +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 +summary: API docs for the @kbn/core-ui-settings-browser-mocks plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] +warning: 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. +--- +import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 4 | 0 | 4 | 0 | + +## Common + +### Objects + + diff --git a/api_docs/kbn_core_ui_settings_common.devdocs.json b/api_docs/kbn_core_ui_settings_common.devdocs.json new file mode 100644 index 0000000000000..2235802090141 --- /dev/null +++ b/api_docs/kbn_core_ui_settings_common.devdocs.json @@ -0,0 +1,418 @@ +{ + "id": "@kbn/core-ui-settings-common", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.DeprecationSettings", + "type": "Interface", + "tags": [], + "label": "DeprecationSettings", + "description": [ + "\nUiSettings deprecation field options." + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.DeprecationSettings.message", + "type": "string", + "tags": [], + "label": "message", + "description": [ + "Deprecation message" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.DeprecationSettings.docLinksKey", + "type": "string", + "tags": [], + "label": "docLinksKey", + "description": [ + "Key to documentation links" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams", + "type": "Interface", + "tags": [], + "label": "UiSettingsParams", + "description": [ + "\nUiSettings parameters defined by the plugins." + ], + "signature": [ + { + "pluginId": "@kbn/core-ui-settings-common", + "scope": "common", + "docId": "kibKbnCoreUiSettingsCommonPluginApi", + "section": "def-common.UiSettingsParams", + "text": "UiSettingsParams" + }, + "" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.name", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "title in the UI" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.value", + "type": "Uncategorized", + "tags": [], + "label": "value", + "description": [ + "default value to fall back to if a user doesn't provide any" + ], + "signature": [ + "T | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.description", + "type": "string", + "tags": [], + "label": "description", + "description": [ + "description provided to a user in UI" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.category", + "type": "Array", + "tags": [], + "label": "category", + "description": [ + "used to group the configured setting in the UI" + ], + "signature": [ + "string[] | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.options", + "type": "Array", + "tags": [], + "label": "options", + "description": [ + "array of permitted values for this setting" + ], + "signature": [ + "string[] | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.optionLabels", + "type": "Object", + "tags": [], + "label": "optionLabels", + "description": [ + "text labels for 'select' type UI element" + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.requiresPageReload", + "type": "CompoundType", + "tags": [], + "label": "requiresPageReload", + "description": [ + "a flag indicating whether new value applying requires page reloading" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.readonly", + "type": "CompoundType", + "tags": [], + "label": "readonly", + "description": [ + "a flag indicating that value cannot be changed" + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.sensitive", + "type": "CompoundType", + "tags": [], + "label": "sensitive", + "description": [ + "\na flag indicating that value might contain user sensitive data.\nused by telemetry to mask the value of the setting when sent." + ], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [ + "defines a type of UI element {@link UiSettingsType}" + ], + "signature": [ + { + "pluginId": "@kbn/core-ui-settings-common", + "scope": "common", + "docId": "kibKbnCoreUiSettingsCommonPluginApi", + "section": "def-common.UiSettingsType", + "text": "UiSettingsType" + }, + " | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.deprecation", + "type": "Object", + "tags": [], + "label": "deprecation", + "description": [ + "optional deprecation information. Used to generate a deprecation warning." + ], + "signature": [ + { + "pluginId": "@kbn/core-ui-settings-common", + "scope": "common", + "docId": "kibKbnCoreUiSettingsCommonPluginApi", + "section": "def-common.DeprecationSettings", + "text": "DeprecationSettings" + }, + " | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.order", + "type": "number", + "tags": [], + "label": "order", + "description": [ + "\nindex of the settings within its category (ascending order, smallest will be displayed first).\nUsed for ordering in the UI.\n" + ], + "signature": [ + "number | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [], + "signature": [ + "Type", + "" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsParams.metric", + "type": "Object", + "tags": [ + "deprecated" + ], + "label": "metric", + "description": [ + "\nMetric to track once this property changes" + ], + "signature": [ + "{ type: string; name: string; } | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": true, + "references": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UserProvidedValues", + "type": "Interface", + "tags": [], + "label": "UserProvidedValues", + "description": [ + "\nDescribes the values explicitly set by user." + ], + "signature": [ + { + "pluginId": "@kbn/core-ui-settings-common", + "scope": "common", + "docId": "kibKbnCoreUiSettingsCommonPluginApi", + "section": "def-common.UserProvidedValues", + "text": "UserProvidedValues" + }, + "" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UserProvidedValues.userValue", + "type": "Uncategorized", + "tags": [], + "label": "userValue", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UserProvidedValues.isOverridden", + "type": "CompoundType", + "tags": [], + "label": "isOverridden", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.PublicUiSettingsParams", + "type": "Type", + "tags": [], + "label": "PublicUiSettingsParams", + "description": [ + "\nA sub-set of {@link UiSettingsParams} exposed to the client-side." + ], + "signature": [ + "{ metric?: { type: string; name: string; } | undefined; type?: ", + { + "pluginId": "@kbn/core-ui-settings-common", + "scope": "common", + "docId": "kibKbnCoreUiSettingsCommonPluginApi", + "section": "def-common.UiSettingsType", + "text": "UiSettingsType" + }, + " | undefined; value?: unknown; description?: string | undefined; name?: string | undefined; options?: string[] | undefined; order?: number | undefined; category?: string[] | undefined; optionLabels?: Record | undefined; requiresPageReload?: boolean | undefined; readonly?: boolean | undefined; sensitive?: boolean | undefined; deprecation?: ", + { + "pluginId": "@kbn/core-ui-settings-common", + "scope": "common", + "docId": "kibKbnCoreUiSettingsCommonPluginApi", + "section": "def-common.DeprecationSettings", + "text": "DeprecationSettings" + }, + " | undefined; }" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-ui-settings-common", + "id": "def-common.UiSettingsType", + "type": "Type", + "tags": [], + "label": "UiSettingsType", + "description": [ + "\nUI element type to represent the settings." + ], + "signature": [ + "\"string\" | \"number\" | \"boolean\" | \"undefined\" | \"color\" | \"image\" | \"json\" | \"markdown\" | \"select\" | \"array\"" + ], + "path": "packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts", + "deprecated": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx new file mode 100644 index 0000000000000..23fdc0fbbb4b1 --- /dev/null +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -0,0 +1,30 @@ +--- +id: kibKbnCoreUiSettingsCommonPluginApi +slug: /kibana-dev-docs/api/kbn-core-ui-settings-common +title: "@kbn/core-ui-settings-common" +image: https://source.unsplash.com/400x175/?github +summary: API docs for the @kbn/core-ui-settings-common plugin +date: 2022-07-18 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] +warning: 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. +--- +import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 23 | 0 | 3 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 7c0e6e7648ffa..6f7957c630a53 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/crypto plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] warning: 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. --- diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 6017c04753893..d6b0356977827 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/crypto-browser plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] warning: 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. --- diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 87f44ac0da128..9afd0dcb509c9 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/datemath plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] warning: 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. --- diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 0889027b5ed49..03600c8eb5123 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-cli-errors plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] warning: 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. --- diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index 759f8039981f8..6bdf5aa06e72c 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-cli-runner plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] warning: 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. --- diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 2d5e8095c3ffd..d253ef68e24c3 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-proc-runner plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] warning: 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. --- diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 2a578260588bf..f2a033462df43 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/dev-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] warning: 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. --- diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 00ef15c27f6c6..ccd05b0cc3e09 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/doc-links plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] warning: 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. --- diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 1745e95ece2ba..1e10f69a21a83 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/docs-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] warning: 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. --- diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 59a8a0413c64c..c6fc992be9393 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/es-archiver plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] warning: 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. --- diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 65d64b1d89a75..6ef0c21af4c5e 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/es-errors plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] warning: 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. --- diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 9084761693e28..d05af5b78d295 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/es-query plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] warning: 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. --- diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 46381bd6e4ed9..4edb84d4b6f84 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] warning: 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. --- diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 851a8217b16ca..6e36e0e05ad87 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/field-types plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] warning: 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. --- diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index c1e107406b828..0eb4654b5bf20 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/find-used-node-modules plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] warning: 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. --- diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index b77f7771f716b..1163450e2232d 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/generate plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] warning: 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. --- diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index c9dfd16d549fe..d6a83c7a111dd 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/handlebars plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] warning: 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. --- diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 74193484aaa01..a07e42898b671 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/hapi-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] warning: 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. --- diff --git a/api_docs/kbn_home_sample_data_cards.mdx b/api_docs/kbn_home_sample_data_cards.mdx index ff0d667da085f..db1a613b06d6c 100644 --- a/api_docs/kbn_home_sample_data_cards.mdx +++ b/api_docs/kbn_home_sample_data_cards.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-cards title: "@kbn/home-sample-data-cards" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/home-sample-data-cards plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-cards'] warning: 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. --- diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index c8164c7778e15..075fb77a3bc3d 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/i18n plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] warning: 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. --- diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 95f220bd9fb5b..da9402421dfe0 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/import-resolver plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] warning: 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. --- diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index ea07bac765030..d50295a4ec191 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/interpreter plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] warning: 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. --- diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 2b5ce56a5d60f..6225ad6ec4557 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/io-ts-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] warning: 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. --- diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index a994586c8a74e..86adaf6b57caf 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/jest-serializers plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] warning: 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. --- diff --git a/api_docs/kbn_kibana_json_schema.mdx b/api_docs/kbn_kibana_json_schema.mdx index e351775e76cee..060dd4b8d4d68 100644 --- a/api_docs/kbn_kibana_json_schema.mdx +++ b/api_docs/kbn_kibana_json_schema.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-json-schema title: "@kbn/kibana-json-schema" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/kibana-json-schema plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-json-schema'] warning: 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. --- diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index d2b10fc180773..c5c7008c24864 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/logging plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] warning: 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. --- diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index e6ebec63e1632..dde39f95ede19 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/logging-mocks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] warning: 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. --- diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 28115f56adc24..34d516e763d7b 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/mapbox-gl plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] warning: 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. --- diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index d9073ce0d303d..31a8a30520ad4 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ml-agg-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] warning: 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. --- diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index a9e31ddb35448..ec5e697e62b51 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] warning: 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. --- diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index f9f2be975e065..6276d93899862 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ml-string-hash plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] warning: 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. --- diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index c51c233e79489..aa6e84684d17d 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/monaco plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] warning: 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. --- diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 26d65a3ead693..53cb7f182e8a4 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/optimizer plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] warning: 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. --- diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 401301b348c9e..dd0e223253062 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] warning: 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. --- diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index f57e25cf322cb..3f34b02b91b48 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] warning: 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. --- diff --git a/api_docs/kbn_plugin_discovery.mdx b/api_docs/kbn_plugin_discovery.mdx index 55e9a6b95abc0..88fe307c3bb68 100644 --- a/api_docs/kbn_plugin_discovery.mdx +++ b/api_docs/kbn_plugin_discovery.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-discovery title: "@kbn/plugin-discovery" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/plugin-discovery plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-discovery'] warning: 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. --- diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index e4578b1f4a432..8fd712b5b411c 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/plugin-generator plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] warning: 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. --- diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 4374d72505a63..6b97051fcdb19 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/plugin-helpers plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] warning: 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. --- diff --git a/api_docs/kbn_pm.mdx b/api_docs/kbn_pm.mdx index da5a74d30c957..35d2d53fe1f27 100644 --- a/api_docs/kbn_pm.mdx +++ b/api_docs/kbn_pm.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-pm title: "@kbn/pm" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/pm plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/pm'] warning: 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. --- diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index ca8e694697cd0..b266903d804a1 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/react-field plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] warning: 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. --- diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 5482e0bedb1a2..df8fc918caa55 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/rule-data-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] warning: 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. --- diff --git a/api_docs/kbn_scalability_simulation_generator.mdx b/api_docs/kbn_scalability_simulation_generator.mdx index e79d76f12349e..6837d445a7fc9 100644 --- a/api_docs/kbn_scalability_simulation_generator.mdx +++ b/api_docs/kbn_scalability_simulation_generator.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-scalability-simulation-generator title: "@kbn/scalability-simulation-generator" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/scalability-simulation-generator plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/scalability-simulation-generator'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index e8ccd05d48c9a..3525dc4f99105 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 6c944bcd5e19e..13324d6db4bf7 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 6728b6ba14dee..917cf96bda219 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 347d01b914dbc..3204dca062a8f 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 833b86fa341b0..9202a6895ce3e 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 762606a0b72b1..c8166732e0803 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 71a19be9283bf..49abef4547851 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index b85e37444435f..9590689c96737 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index fe27d37be1ed7..9d11456c16e33 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 36797c388c072..02f9e584734f3 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 192b8ec9d7554..0355d79061d7d 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 26020f321d906..e7463195dbab2 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-rules plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 39c4712d09079..e54bceb33b5cc 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] warning: 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. --- diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index bb30474236d0c..31fe8429dd093 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/securitysolution-utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] warning: 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. --- diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 2ae808a2f4544..fa72055f1df6b 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/server-http-tools plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] warning: 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. --- diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index a8d94e51fd268..dd031b26b7833 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/server-route-repository plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] warning: 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. --- diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 4fc6f96dc869a..689c18a2717d6 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] warning: 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. --- diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 3120a76d22182..28abe15482191 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] warning: 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. --- diff --git a/api_docs/kbn_shared_ux_components.mdx b/api_docs/kbn_shared_ux_components.mdx index 55b064588053a..0f3d503e8e6e5 100644 --- a/api_docs/kbn_shared_ux_components.mdx +++ b/api_docs/kbn_shared_ux_components.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-components title: "@kbn/shared-ux-components" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-components plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-components'] warning: 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. --- 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 b2c92e8913396..06cf6b161b9cf 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] warning: 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. --- 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 d1c4b518a2b54..65e9ef61788d6 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] warning: 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. --- diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index ec5eb2ca715e7..74497e91f9e62 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] warning: 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. --- 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 3cd347e515853..b3b4e5019602c 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -4,7 +4,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 summary: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] warning: 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. --- diff --git a/api_docs/kbn_shared_ux_services.mdx b/api_docs/kbn_shared_ux_services.mdx index 0d2aefce71fdc..fe3d5e7b86513 100644 --- a/api_docs/kbn_shared_ux_services.mdx +++ b/api_docs/kbn_shared_ux_services.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-services title: "@kbn/shared-ux-services" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-services plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-services'] warning: 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. --- diff --git a/api_docs/kbn_shared_ux_storybook.mdx b/api_docs/kbn_shared_ux_storybook.mdx index 42b4f931b1d85..839053658b099 100644 --- a/api_docs/kbn_shared_ux_storybook.mdx +++ b/api_docs/kbn_shared_ux_storybook.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook title: "@kbn/shared-ux-storybook" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-storybook plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook'] warning: 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. --- diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 711fb0e0cd990..e016371b504bf 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/shared-ux-utility plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] warning: 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. --- diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 5ae42cf4f2d29..f0a03ba8cdd9f 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/sort-package-json plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] warning: 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. --- diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 00e47f058bb0e..09b22d7c14368 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/std plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] warning: 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. --- diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index a3912ad4534f4..9a7dc545fe43c 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] warning: 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. --- diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 6bd0a35d7781a..881e3c2572eb9 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/storybook plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] warning: 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. --- diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 01f7ecfa62fa7..f426b55e05a9e 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/telemetry-tools plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] warning: 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. --- diff --git a/api_docs/kbn_test.devdocs.json b/api_docs/kbn_test.devdocs.json index 0304ca46ffea1..2fdec23b80a59 100644 --- a/api_docs/kbn_test.devdocs.json +++ b/api_docs/kbn_test.devdocs.json @@ -3008,7 +3008,7 @@ "\nDetermine if a service is avaliable" ], "signature": [ - "{ (serviceName: \"log\" | \"config\" | \"lifecycle\" | \"dockerServers\" | \"esVersion\"): true; (serviceName: K): serviceName is K; (serviceName: string): serviceName is Extract; }" + "{ (serviceName: \"log\" | \"config\" | \"lifecycle\" | \"dockerServers\" | \"esVersion\" | \"dedicatedTaskRunner\"): true; (serviceName: K): serviceName is K; (serviceName: string): serviceName is Extract; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", "deprecated": false, @@ -3021,7 +3021,7 @@ "label": "serviceName", "description": [], "signature": [ - "\"log\" | \"config\" | \"lifecycle\" | \"dockerServers\" | \"esVersion\"" + "\"log\" | \"config\" | \"lifecycle\" | \"dockerServers\" | \"esVersion\" | \"dedicatedTaskRunner\"" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", "deprecated": false, @@ -3038,7 +3038,7 @@ "label": "hasService", "description": [], "signature": [ - "{ (serviceName: \"log\" | \"config\" | \"lifecycle\" | \"dockerServers\" | \"esVersion\"): true; (serviceName: K): serviceName is K; (serviceName: string): serviceName is Extract; }" + "{ (serviceName: \"log\" | \"config\" | \"lifecycle\" | \"dockerServers\" | \"esVersion\" | \"dedicatedTaskRunner\"): true; (serviceName: K): serviceName is K; (serviceName: string): serviceName is Extract; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", "deprecated": false, @@ -3068,7 +3068,7 @@ "label": "hasService", "description": [], "signature": [ - "{ (serviceName: \"log\" | \"config\" | \"lifecycle\" | \"dockerServers\" | \"esVersion\"): true; (serviceName: K): serviceName is K; (serviceName: string): serviceName is Extract; }" + "{ (serviceName: \"log\" | \"config\" | \"lifecycle\" | \"dockerServers\" | \"esVersion\" | \"dedicatedTaskRunner\"): true; (serviceName: K): serviceName is K; (serviceName: string): serviceName is Extract; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", "deprecated": false, @@ -3134,6 +3134,8 @@ "section": "def-server.EsVersion", "text": "EsVersion" }, + "; (serviceName: \"dedicatedTaskRunner\"): ", + "DedicatedTaskRunner", "; (serviceName: T): ServiceMap[T]; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", @@ -3198,6 +3200,8 @@ "section": "def-server.EsVersion", "text": "EsVersion" }, + "; (serviceName: \"dedicatedTaskRunner\"): ", + "DedicatedTaskRunner", "; (serviceName: T): ServiceMap[T]; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", @@ -3262,6 +3266,8 @@ "section": "def-server.EsVersion", "text": "EsVersion" }, + "; (serviceName: \"dedicatedTaskRunner\"): ", + "DedicatedTaskRunner", "; (serviceName: T): ServiceMap[T]; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", @@ -3326,6 +3332,8 @@ "section": "def-server.EsVersion", "text": "EsVersion" }, + "; (serviceName: \"dedicatedTaskRunner\"): ", + "DedicatedTaskRunner", "; (serviceName: T): ServiceMap[T]; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", @@ -3390,6 +3398,8 @@ "section": "def-server.EsVersion", "text": "EsVersion" }, + "; (serviceName: \"dedicatedTaskRunner\"): ", + "DedicatedTaskRunner", "; (serviceName: T): ServiceMap[T]; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", @@ -3454,6 +3464,74 @@ "section": "def-server.EsVersion", "text": "EsVersion" }, + "; (serviceName: \"dedicatedTaskRunner\"): ", + "DedicatedTaskRunner", + "; (serviceName: T): ServiceMap[T]; }" + ], + "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@kbn/test", + "id": "def-server.GenericFtrProviderContext.getService.$1", + "type": "string", + "tags": [], + "label": "serviceName", + "description": [], + "signature": [ + "\"dedicatedTaskRunner\"" + ], + "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/test", + "id": "def-server.GenericFtrProviderContext.getService", + "type": "Function", + "tags": [], + "label": "getService", + "description": [], + "signature": [ + "{ (serviceName: \"config\"): ", + { + "pluginId": "@kbn/test", + "scope": "server", + "docId": "kibKbnTestPluginApi", + "section": "def-server.Config", + "text": "Config" + }, + "; (serviceName: \"log\"): ", + "ToolingLog", + "; (serviceName: \"lifecycle\"): ", + { + "pluginId": "@kbn/test", + "scope": "server", + "docId": "kibKbnTestPluginApi", + "section": "def-server.Lifecycle", + "text": "Lifecycle" + }, + "; (serviceName: \"dockerServers\"): ", + { + "pluginId": "@kbn/test", + "scope": "server", + "docId": "kibKbnTestPluginApi", + "section": "def-server.DockerServersService", + "text": "DockerServersService" + }, + "; (serviceName: \"esVersion\"): ", + { + "pluginId": "@kbn/test", + "scope": "server", + "docId": "kibKbnTestPluginApi", + "section": "def-server.EsVersion", + "text": "EsVersion" + }, + "; (serviceName: \"dedicatedTaskRunner\"): ", + "DedicatedTaskRunner", "; (serviceName: T): ServiceMap[T]; }" ], "path": "packages/kbn-test/src/functional_test_runner/public_types.ts", @@ -4085,17 +4163,6 @@ "deprecated": false, "initialIsOpen": false }, - { - "parentPluginId": "@kbn/test", - "id": "def-server.KIBANA_ROOT", - "type": "string", - "tags": [], - "label": "KIBANA_ROOT", - "description": [], - "path": "packages/kbn-test/src/functional_tests/lib/paths.ts", - "deprecated": false, - "initialIsOpen": false - }, { "parentPluginId": "@kbn/test", "id": "def-server.ProvidedType", diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index e02a0e7631088..4c9700cef79cd 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/test plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] warning: 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. --- @@ -18,7 +18,7 @@ Contact Operations for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 251 | 5 | 210 | 10 | +| 252 | 5 | 211 | 11 | ## Server diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index e5a7fbdfff162..05642fd07db93 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/test-jest-helpers plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] warning: 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. --- diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index f5328706fcf4b..b2513a85dacb3 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/tooling-log plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] warning: 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. --- diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index f243d4dc40658..db9c165b4e4d4 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/type-summarizer plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] warning: 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. --- diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index 82bdca5e9d8b2..eb74684b282c9 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/type-summarizer-core plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] warning: 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. --- diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 3bb61421b625d..16918024301ab 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/typed-react-router-config plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] warning: 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. --- diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 1b007f581dd8f..41296d33bb354 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/ui-theme plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] warning: 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. --- diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 6464c4216069e..d6ffd66a3c4ea 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/utility-types plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] warning: 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. --- diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index f1ca30178f685..34329cafcf352 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/utility-types-jest plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] warning: 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. --- diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index 66520bf1db066..5fed058183a56 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github summary: API docs for the @kbn/utils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] warning: 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. --- diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index ca0fd397bc94c..1399e76c0e754 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaOverview plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] warning: 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. --- diff --git a/api_docs/kibana_react.devdocs.json b/api_docs/kibana_react.devdocs.json index 921e088a13418..1b233147eb7da 100644 --- a/api_docs/kibana_react.devdocs.json +++ b/api_docs/kibana_react.devdocs.json @@ -1076,18 +1076,6 @@ "plugin": "canvas", "path": "x-pack/plugins/canvas/public/components/home/home.component.tsx" }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, { "plugin": "enterpriseSearch", "path": "x-pack/plugins/enterprise_search/public/applications/shared/version_mismatch/version_mismatch_page.tsx" @@ -1114,15 +1102,15 @@ }, { "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx" + "path": "x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx" }, { "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx" + "path": "x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx" }, { "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx" + "path": "x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx" }, { "plugin": "enterpriseSearch", @@ -1136,18 +1124,6 @@ "plugin": "enterpriseSearch", "path": "x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/error_connecting/error_connecting.tsx" }, - { - "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx" - }, - { - "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx" - }, - { - "plugin": "enterpriseSearch", - "path": "x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx" - }, { "plugin": "enterpriseSearch", "path": "x-pack/plugins/enterprise_search/public/applications/app_search/components/error_connecting/error_connecting.tsx" @@ -4263,54 +4239,6 @@ "plugin": "management", "path": "src/plugins/management/public/components/management_app/management_app.tsx" }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx" - }, - { - "plugin": "cloudSecurityPosture", - "path": "x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx" - }, { "plugin": "enterpriseSearch", "path": "x-pack/plugins/enterprise_search/public/applications/shared/layout/page_template.tsx" @@ -4381,23 +4309,11 @@ "text": "OverlayStart" }, " | undefined; uiSettings?: ", - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - }, + "IUiSettingsClient", " | undefined; fatalErrors?: ", "FatalErrorsSetup", " | undefined; deprecations?: ", - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.DeprecationsServiceStart", - "text": "DeprecationsServiceStart" - }, + "DeprecationsServiceStart", " | undefined; theme?: ", "ThemeServiceStart", " | undefined; injectedMetadata?: ", diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 3c4b6ed0309fc..052007a4588ae 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaReact plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] warning: 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. --- diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index e57d0e2d3b29e..b1513686419f1 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github summary: API docs for the kibanaUtils plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] warning: 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. --- diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 736bf513869f4..f6d9bfd13c9a4 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github summary: API docs for the kubernetesSecurity plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] warning: 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. --- diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index 990dbbafbda78..406a04922c602 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -1007,10 +1007,10 @@ }, { "parentPluginId": "lens", - "id": "def-public.DataLayerArgs.hide", + "id": "def-public.DataLayerArgs.simpleView", "type": "CompoundType", "tags": [], - "label": "hide", + "label": "simpleView", "description": [], "signature": [ "boolean | undefined" @@ -5402,10 +5402,10 @@ }, { "parentPluginId": "lens", - "id": "def-public.XYAnnotationLayerConfig.hide", + "id": "def-public.XYAnnotationLayerConfig.simpleView", "type": "CompoundType", "tags": [], - "label": "hide", + "label": "simpleView", "description": [], "signature": [ "boolean | undefined" @@ -5889,10 +5889,10 @@ }, { "parentPluginId": "lens", - "id": "def-public.XYDataLayerConfig.hide", + "id": "def-public.XYDataLayerConfig.simpleView", "type": "CompoundType", "tags": [], - "label": "hide", + "label": "simpleView", "description": [], "signature": [ "boolean | undefined" @@ -9944,7 +9944,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined) => ", { @@ -9974,7 +9974,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined" ], diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 1c49503e62394..2e76b573df50d 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github summary: API docs for the lens plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] warning: 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. --- diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 331b37523bb0b..e913f79eabf7a 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github summary: API docs for the licenseApiGuard plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] warning: 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. --- diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 7d70dd7118c5b..9dd5201006e01 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the licenseManagement plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] warning: 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. --- diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index dce399078a361..51fbbdcb31f45 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github summary: API docs for the licensing plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] warning: 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. --- diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index c5bf01ce7e4e4..004c84ac41387 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github summary: API docs for the lists plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] warning: 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. --- diff --git a/api_docs/management.mdx b/api_docs/management.mdx index d0fe3a0d4d7c6..86501943aa688 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github summary: API docs for the management plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] warning: 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. --- diff --git a/api_docs/maps.devdocs.json b/api_docs/maps.devdocs.json index f25dab745052a..4732fd45134ad 100644 --- a/api_docs/maps.devdocs.json +++ b/api_docs/maps.devdocs.json @@ -644,6 +644,21 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "maps", + "id": "def-public.MapEmbeddable._getIsFilterByMapExtent", + "type": "Function", + "tags": [], + "label": "_getIsFilterByMapExtent", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "x-pack/plugins/maps/public/embeddable/map_embeddable.tsx", + "deprecated": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "maps", "id": "def-public.MapEmbeddable._gotoSynchronizedLocation", @@ -1093,25 +1108,25 @@ }, { "parentPluginId": "maps", - "id": "def-public.MapEmbeddable.setMapExtentFilter", + "id": "def-public.MapEmbeddable._setMapExtentFilter", "type": "Function", "tags": [], - "label": "setMapExtentFilter", + "label": "_setMapExtentFilter", "description": [], "signature": [ - "() => void" + "(() => void) & _.Cancelable" ], "path": "x-pack/plugins/maps/public/embeddable/map_embeddable.tsx", "deprecated": false, - "children": [], - "returnComment": [] + "returnComment": [], + "children": [] }, { "parentPluginId": "maps", - "id": "def-public.MapEmbeddable.clearMapExtentFilter", + "id": "def-public.MapEmbeddable._clearMapExtentFilter", "type": "Function", "tags": [], - "label": "clearMapExtentFilter", + "label": "_clearMapExtentFilter", "description": [], "signature": [ "() => void" diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index c3af9f2b2b8ce..4f722ea011179 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github summary: API docs for the maps plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [GIS](https://github.com/orgs/elastic/teams/kibana-gis) for questions re | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 249 | 0 | 248 | 24 | +| 250 | 0 | 249 | 24 | ## Client diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 8d4fa80184619..aa99a0d006914 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github summary: API docs for the mapsEms plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] warning: 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. --- diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 7cf5e6f08934f..ecf3540a26754 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github summary: API docs for the ml plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] warning: 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. --- diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 9a96f5fb71459..00de65b67c3ce 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github summary: API docs for the monitoring plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] warning: 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. --- diff --git a/api_docs/monitoring_collection.devdocs.json b/api_docs/monitoring_collection.devdocs.json index bca169a38e523..00992e0736f7f 100644 --- a/api_docs/monitoring_collection.devdocs.json +++ b/api_docs/monitoring_collection.devdocs.json @@ -119,7 +119,7 @@ "label": "MonitoringCollectionConfig", "description": [], "signature": [ - "{ readonly enabled: boolean; }" + "{ readonly enabled: boolean; readonly opentelemetry: Readonly<{} & { metrics: Readonly<{} & { otlp: Readonly<{ url?: string | undefined; headers?: Record | undefined; } & { exportIntervalMillis: number; logLevel: string; }>; prometheus: Readonly<{} & { enabled: boolean; }>; }>; }>; }" ], "path": "x-pack/plugins/monitoring_collection/server/config.ts", "deprecated": false, diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index dd904b036cb13..8409f4b3e6e7a 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github summary: API docs for the monitoringCollection plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] warning: 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. --- diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index c34729aae4333..f554bf3e4a482 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github summary: API docs for the navigation plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] warning: 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. --- diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 9fd49bf331ce3..d647814d34fc8 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github summary: API docs for the newsfeed plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] warning: 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. --- diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index b7ed67de04c43..58534e319fad7 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -205,7 +205,7 @@ "section": "def-public.ObservabilityRuleTypeFormatter", "text": "ObservabilityRuleTypeFormatter" }, - " | undefined; list: () => string[]; } & { getFormatter: () => () => string; registerFormatter: () => void; }" + " | undefined; list: () => string[]; } & { getFormatter: () => () => string; registerFormatter: () => void; list: () => string[]; }" ], "path": "x-pack/plugins/observability/public/rules/observability_rule_type_registry_mock.ts", "deprecated": false, @@ -3364,60 +3364,99 @@ }, { "parentPluginId": "observability", - "id": "def-public.ObservabilityPublicPluginsStart.features", + "id": "def-public.ObservabilityPublicPluginsStart.sharedUX", "type": "Object", "tags": [], - "label": "features", + "label": "sharedUX", "description": [], "signature": [ - "{ getFeatures: () => Promise<", { - "pluginId": "features", - "scope": "common", - "docId": "kibFeaturesPluginApi", - "section": "def-common.KibanaFeature", - "text": "KibanaFeature" - }, - "[]>; }" + "pluginId": "sharedUX", + "scope": "public", + "docId": "kibSharedUXPluginApi", + "section": "def-public.SharedUXPluginStart", + "text": "SharedUXPluginStart" + } ], "path": "x-pack/plugins/observability/public/plugin.ts", "deprecated": false }, { "parentPluginId": "observability", - "id": "def-public.ObservabilityPublicPluginsStart.kibanaFeatures", - "type": "Array", + "id": "def-public.ObservabilityPublicPluginsStart.ruleTypeRegistry", + "type": "Object", "tags": [], - "label": "kibanaFeatures", + "label": "ruleTypeRegistry", "description": [], "signature": [ + "{ list: () => ", { - "pluginId": "features", + "pluginId": "triggersActionsUi", + "scope": "public", + "docId": "kibTriggersActionsUiPluginApi", + "section": "def-public.RuleTypeModel", + "text": "RuleTypeModel" + }, + "<", + { + "pluginId": "alerting", "scope": "common", - "docId": "kibFeaturesPluginApi", - "section": "def-common.KibanaFeature", - "text": "KibanaFeature" + "docId": "kibAlertingPluginApi", + "section": "def-common.RuleTypeParams", + "text": "RuleTypeParams" }, - "[]" + ">[]; get: (id: string) => ", + { + "pluginId": "triggersActionsUi", + "scope": "public", + "docId": "kibTriggersActionsUiPluginApi", + "section": "def-public.RuleTypeModel", + "text": "RuleTypeModel" + }, + "<", + { + "pluginId": "alerting", + "scope": "common", + "docId": "kibAlertingPluginApi", + "section": "def-common.RuleTypeParams", + "text": "RuleTypeParams" + }, + ">; register: (objectType: ", + { + "pluginId": "triggersActionsUi", + "scope": "public", + "docId": "kibTriggersActionsUiPluginApi", + "section": "def-public.RuleTypeModel", + "text": "RuleTypeModel" + }, + "<", + { + "pluginId": "alerting", + "scope": "common", + "docId": "kibAlertingPluginApi", + "section": "def-common.RuleTypeParams", + "text": "RuleTypeParams" + }, + ">) => void; has: (id: string) => boolean; }" ], "path": "x-pack/plugins/observability/public/plugin.ts", "deprecated": false }, { "parentPluginId": "observability", - "id": "def-public.ObservabilityPublicPluginsStart.sharedUX", + "id": "def-public.ObservabilityPublicPluginsStart.actionTypeRegistry", "type": "Object", "tags": [], - "label": "sharedUX", + "label": "actionTypeRegistry", "description": [], "signature": [ - { - "pluginId": "sharedUX", - "scope": "public", - "docId": "kibSharedUXPluginApi", - "section": "def-public.SharedUXPluginStart", - "text": "SharedUXPluginStart" - } + "{ list: () => ", + "ActionTypeModel", + "[]; get: (id: string) => ", + "ActionTypeModel", + "; register: (objectType: ", + "ActionTypeModel", + ") => void; has: (id: string) => boolean; }" ], "path": "x-pack/plugins/observability/public/plugin.ts", "deprecated": false diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 71cfee396b9d1..3dd22a2322057 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github summary: API docs for the observability plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] warning: 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. --- diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 52aac69572b83..45b10f6a2109e 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github summary: API docs for the osquery plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] warning: 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. --- diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 80e714e48ffa2..0f422f6cae03f 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -3,7 +3,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory summary: Directory of public APIs available through plugins or packages. -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana'] warning: 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. --- @@ -12,13 +12,13 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 335 | 276 | 36 | +| 350 | 290 | 36 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 27414 | 172 | 19519 | 1433 | +| 27662 | 176 | 19688 | 1464 | ## Plugin Directory @@ -26,7 +26,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex |--------------|----------------|-----------|--------------|----------|---------------|--------| | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 241 | 0 | 236 | 19 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 23 | 0 | 19 | 1 | -| | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 12 | 0 | 0 | 0 | +| | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 9 | 0 | 0 | 1 | | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 365 | 0 | 356 | 20 | | | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 40 | 0 | 40 | 55 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | @@ -38,14 +38,14 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Cloud Security Posture](https://github.com/orgs/elastic/teams/cloud-posture-security) | The cloud security posture plugin | 6 | 0 | 6 | 0 | | | [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 | 206 | 0 | 198 | 7 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2489 | 9 | 746 | 25 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2472 | 5 | 705 | 17 | | crossClusterReplication | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 102 | 0 | 83 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 143 | 0 | 141 | 12 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 52 | 0 | 51 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3075 | 34 | 2402 | 21 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | This plugin provides the ability to create data views via a modal flyout from any kibana app | 14 | 0 | 7 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 42 | 0 | 37 | 3 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | This plugin provides the ability to create data views via a modal flyout from any kibana app | 15 | 0 | 7 | 0 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 41 | 0 | 36 | 3 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data view management app | 2 | 0 | 2 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 938 | 1 | 199 | 1 | | | [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 | @@ -76,7 +76,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 222 | 0 | 95 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 288 | 5 | 249 | 3 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1522 | 8 | 1390 | 10 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1537 | 8 | 1405 | 10 | | | [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 | @@ -102,7 +102,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Security detections response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 198 | 0 | 90 | 49 | | logstash | [Logstash](https://github.com/orgs/elastic/teams/logstash) | - | 0 | 0 | 0 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 41 | 0 | 41 | 6 | -| | [GIS](https://github.com/orgs/elastic/teams/kibana-gis) | - | 249 | 0 | 248 | 24 | +| | [GIS](https://github.com/orgs/elastic/teams/kibana-gis) | - | 250 | 0 | 249 | 24 | | | [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. | 251 | 10 | 78 | 31 | | | [Stack Monitoring](https://github.com/orgs/elastic/teams/stack-monitoring-ui) | - | 11 | 0 | 9 | 1 | @@ -126,7 +126,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [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 | | | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 197 | 0 | 100 | 0 | -| | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 52 | 0 | 51 | 21 | +| | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 52 | 0 | 51 | 22 | | | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 3 | 0 | 3 | 1 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds URL Service and sharing capabilities to Kibana | 114 | 0 | 55 | 10 | | | [Shared UX](https://github.com/orgs/elastic/teams/shared-ux) | A plugin providing components and services for shared user experiences in Kibana. | 4 | 0 | 0 | 0 | @@ -135,14 +135,14 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 4 | 0 | 4 | 0 | | synthetics | [Uptime](https://github.com/orgs/elastic/teams/uptime) | This plugin visualizes data from Synthetics and Heartbeat, and integrates with other Observability solutions. | 0 | 0 | 0 | 0 | | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 82 | 0 | 41 | 7 | -| | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 43 | 0 | 1 | 0 | +| | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 44 | 0 | 1 | 0 | | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 32 | 0 | 32 | 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 | | | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 447 | 1 | 342 | 32 | | | [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) | - | 412 | 0 | 391 | 40 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 407 | 0 | 386 | 42 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds UI Actions service to Kibana | 130 | 0 | 91 | 11 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 205 | 0 | 142 | 9 | | | [Unified Search](https://github.com/orgs/elastic/teams/kibana-app-services) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 82 | 2 | 78 | 13 | @@ -206,6 +206,10 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Owner missing] | - | 7 | 0 | 7 | 0 | | | [Owner missing] | - | 3 | 0 | 3 | 0 | | | [Owner missing] | - | 15 | 0 | 13 | 0 | +| | [Owner missing] | - | 9 | 0 | 3 | 0 | +| | [Owner missing] | - | 6 | 0 | 6 | 0 | +| | [Owner missing] | - | 4 | 0 | 4 | 0 | +| | [Owner missing] | - | 17 | 0 | 9 | 0 | | | [Owner missing] | - | 4 | 0 | 4 | 0 | | | [Owner missing] | - | 4 | 0 | 4 | 0 | | | [Owner missing] | - | 5 | 0 | 2 | 0 | @@ -225,7 +229,12 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Owner missing] | - | 10 | 0 | 10 | 0 | | | [Owner missing] | - | 16 | 0 | 16 | 0 | | | [Owner missing] | - | 4 | 0 | 0 | 0 | +| | [Owner missing] | - | 10 | 1 | 10 | 0 | +| | [Owner missing] | - | 25 | 5 | 25 | 1 | +| | [Owner missing] | - | 7 | 0 | 7 | 1 | | | [Owner missing] | - | 392 | 1 | 154 | 0 | +| | [Owner missing] | - | 54 | 0 | 48 | 2 | +| | [Owner missing] | - | 41 | 0 | 37 | 0 | | | [Owner missing] | - | 4 | 0 | 2 | 0 | | | [Owner missing] | - | 3 | 0 | 3 | 0 | | | [Owner missing] | - | 8 | 2 | 6 | 0 | @@ -238,9 +247,14 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Owner missing] | - | 3 | 0 | 3 | 0 | | | [Owner missing] | - | 5 | 0 | 0 | 0 | | | [Owner missing] | - | 6 | 0 | 6 | 0 | +| | [Owner missing] | - | 5 | 0 | 5 | 0 | | | [Owner missing] | - | 6 | 0 | 4 | 0 | | | [Owner missing] | - | 2 | 0 | 1 | 0 | | | [Owner missing] | - | 6 | 0 | 6 | 0 | +| | [Owner missing] | - | 25 | 1 | 13 | 0 | +| | [Owner missing] | - | 25 | 1 | 25 | 0 | +| | [Owner missing] | - | 4 | 0 | 4 | 0 | +| | [Owner missing] | - | 23 | 0 | 3 | 0 | | | [Owner missing] | - | 13 | 0 | 7 | 0 | | | [Owner missing] | - | 10 | 0 | 10 | 0 | | | [Owner missing] | elasticsearch datemath parser, used in kibana | 44 | 0 | 43 | 0 | @@ -314,7 +328,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Owner missing] | - | 4 | 0 | 2 | 0 | | | Operations | - | 38 | 2 | 21 | 0 | | | [Owner missing] | - | 2 | 0 | 2 | 0 | -| | Operations | - | 251 | 5 | 210 | 10 | +| | Operations | - | 252 | 5 | 211 | 11 | | | [Owner missing] | - | 135 | 8 | 103 | 2 | | | [Owner missing] | - | 72 | 0 | 55 | 0 | | | [Owner missing] | - | 8 | 0 | 2 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index c7b08aab4bd73..cd7a619d1cd7a 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github summary: API docs for the presentationUtil plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] warning: 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. --- diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 59c7c219a1602..16ca281504f3a 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github summary: API docs for the remoteClusters plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] warning: 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. --- diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 8d73fbaa1f36a..b3680199c5cfe 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github summary: API docs for the reporting plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] warning: 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. --- diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index deb418b833fe3..caee41f6c8f99 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github summary: API docs for the rollup plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] warning: 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. --- diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index db25b33fb89f9..7ae32ba102995 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github summary: API docs for the ruleRegistry plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] warning: 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. --- diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index e0a004928b4b2..6086df87b3a89 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github summary: API docs for the runtimeFields plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] warning: 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. --- diff --git a/api_docs/saved_objects.devdocs.json b/api_docs/saved_objects.devdocs.json index f0280fde583d7..1f715bff2765f 100644 --- a/api_docs/saved_objects.devdocs.json +++ b/api_docs/saved_objects.devdocs.json @@ -829,13 +829,7 @@ "text": "SavedObjectsStart" }, ", uiSettings: ", - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - }, + "IUiSettingsClient", ") => (props: ", "SavedObjectFinderProps", ") => JSX.Element" @@ -871,13 +865,7 @@ "label": "uiSettings", "description": [], "signature": [ - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - } + "IUiSettingsClient" ], "path": "src/plugins/saved_objects/public/finder/saved_object_finder.tsx", "deprecated": false, @@ -2997,13 +2985,7 @@ "text": "SavedObjectsStart" }, "; uiSettings: ", - { - "pluginId": "core", - "scope": "public", - "docId": "kibCorePluginApi", - "section": "def-public.IUiSettingsClient", - "text": "IUiSettingsClient" - }, + "IUiSettingsClient", "; } & ", "SavedObjectFinderProps" ], diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 2792e2107d074..b94b28329351a 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjects plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] warning: 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. --- diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 4d25d3bf28f50..2ef5ce8554542 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsManagement plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] warning: 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. --- diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 5b61e650b0976..1fc3bd6ca2ca1 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsTagging plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] warning: 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. --- diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 8f7e57b1e2718..1adfd65b7e135 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github summary: API docs for the savedObjectsTaggingOss plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] warning: 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. --- diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 7b042ea1f93c6..37487313d5c21 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github summary: API docs for the screenshotMode plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] warning: 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. --- diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 51a7e1a61919f..f83b7e34a396c 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github summary: API docs for the screenshotting plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] warning: 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. --- diff --git a/api_docs/security.devdocs.json b/api_docs/security.devdocs.json index 17da37f5902c4..f48eba18053c2 100644 --- a/api_docs/security.devdocs.json +++ b/api_docs/security.devdocs.json @@ -2401,13 +2401,7 @@ "label": "errors", "description": [], "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.DeprecationsDetails", - "text": "DeprecationsDetails" - }, + "DeprecationsDetails", "[] | undefined" ], "path": "x-pack/plugins/security/common/model/deprecations.ts", diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 434d136388f5e..dba9501561af0 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github summary: API docs for the security plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] warning: 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. --- diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index 9146fb540b3cc..98575276e9149 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -121,7 +121,7 @@ "text": "CoreSetup" }, "<", - "StartPlugins", + "StartPluginsDependencies", ", ", "PluginStart", ">, plugins: ", @@ -154,7 +154,7 @@ "text": "CoreSetup" }, "<", - "StartPlugins", + "StartPluginsDependencies", ", ", "PluginStart", ">" diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index d1d77eae3d5fc..f41238eea2bcf 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github summary: API docs for the securitySolution plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Security solution](https://github.com/orgs/elastic/teams/security-solut | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 52 | 0 | 51 | 21 | +| 52 | 0 | 51 | 22 | ## Client diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index da2c2cf09a878..0a30a7b5b6a01 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github summary: API docs for the sessionView plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] warning: 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. --- diff --git a/api_docs/share.mdx b/api_docs/share.mdx index b6a02d17aecc4..1ae3fa23eb1fa 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github summary: API docs for the share plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] warning: 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. --- diff --git a/api_docs/shared_u_x.mdx b/api_docs/shared_u_x.mdx index de326e69e0fe2..1df2f203d8232 100644 --- a/api_docs/shared_u_x.mdx +++ b/api_docs/shared_u_x.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/sharedUX title: "sharedUX" image: https://source.unsplash.com/400x175/?github summary: API docs for the sharedUX plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sharedUX'] warning: 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. --- diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 2d533df972c65..f15fdd1193ec6 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github summary: API docs for the snapshotRestore plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] warning: 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. --- diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 2082447ea3258..8673507136d26 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github summary: API docs for the spaces plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] warning: 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. --- diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index e5cce413d231b..fd42a28e7000d 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github summary: API docs for the stackAlerts plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] warning: 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. --- diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 2ca6c69bacca9..1c6d3db965db9 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github summary: API docs for the taskManager plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] warning: 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. --- diff --git a/api_docs/telemetry.devdocs.json b/api_docs/telemetry.devdocs.json index a7909d0329970..d74bba309e07b 100644 --- a/api_docs/telemetry.devdocs.json +++ b/api_docs/telemetry.devdocs.json @@ -161,6 +161,21 @@ ], "path": "src/plugins/telemetry/public/plugin.ts", "deprecated": false + }, + { + "parentPluginId": "telemetry", + "id": "def-public.TelemetryPluginConfig.labels", + "type": "Object", + "tags": [], + "label": "labels", + "description": [ + "Extra labels to add to the telemetry context" + ], + "signature": [ + "{ [x: string]: unknown; }" + ], + "path": "src/plugins/telemetry/public/plugin.ts", + "deprecated": false } ], "initialIsOpen": false diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index b0a927943f987..8875155459652 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetry plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetr | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 43 | 0 | 1 | 0 | +| 44 | 0 | 1 | 0 | ## Client diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 5ed1647e3fd4e..538b4c4a2500c 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryCollectionManager plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] warning: 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. --- diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 421ef5b38c9a8..a3c8722880819 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryCollectionXpack plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] warning: 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. --- diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 3d33d343a8620..d4f93b160e8f5 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github summary: API docs for the telemetryManagementSection plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] warning: 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. --- diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index c384f9da142fc..3728d891114d6 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github summary: API docs for the timelines plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] warning: 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. --- diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index a8e0315881b2d..b3562fec27109 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github summary: API docs for the transform plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] warning: 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. --- diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index 21cdbb34c1e45..308ee72116682 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -1647,7 +1647,7 @@ "label": "useLoadRuleTypes", "description": [], "signature": [ - "({ filteredSolutions }: RuleTypesProps) => { ruleTypes: ", + "({ filteredRuleTypes }: RuleTypesProps) => { ruleTypes: ", { "pluginId": "triggersActionsUi", "scope": "public", @@ -1656,13 +1656,7 @@ "text": "RuleType" }, "[]; error: string | null; ruleTypeIndex: ", - { - "pluginId": "triggersActionsUi", - "scope": "public", - "docId": "kibTriggersActionsUiPluginApi", - "section": "def-public.RuleTypeIndex", - "text": "RuleTypeIndex" - }, + "RuleTypeIndex", "; }" ], "path": "x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts", @@ -1673,7 +1667,7 @@ "id": "def-public.useLoadRuleTypes.$1", "type": "Object", "tags": [], - "label": "{ filteredSolutions }", + "label": "{ filteredRuleTypes }", "description": [], "signature": [ "RuleTypesProps" @@ -2906,105 +2900,16 @@ "deprecated": false, "children": [], "returnComment": [] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleTableItem", - "type": "Interface", - "tags": [], - "label": "RuleTableItem", - "description": [], - "signature": [ - { - "pluginId": "triggersActionsUi", - "scope": "public", - "docId": "kibTriggersActionsUiPluginApi", - "section": "def-public.RuleTableItem", - "text": "RuleTableItem" - }, - " extends ", - { - "pluginId": "triggersActionsUi", - "scope": "public", - "docId": "kibTriggersActionsUiPluginApi", - "section": "def-public.Rule", - "text": "Rule" - }, - "<", - { - "pluginId": "alerting", - "scope": "common", - "docId": "kibAlertingPluginApi", - "section": "def-common.RuleTypeParams", - "text": "RuleTypeParams" - }, - ">" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleTableItem.ruleType", - "type": "string", - "tags": [], - "label": "ruleType", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", - "deprecated": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleTableItem.index", - "type": "number", - "tags": [], - "label": "index", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", - "deprecated": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleTableItem.actionsCount", - "type": "number", - "tags": [], - "label": "actionsCount", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", - "deprecated": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleTableItem.isEditable", - "type": "boolean", - "tags": [], - "label": "isEditable", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", - "deprecated": false }, { "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleTableItem.enabledInLicense", - "type": "boolean", - "tags": [], - "label": "enabledInLicense", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", - "deprecated": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleTableItem.showIntervalWarning", - "type": "CompoundType", + "id": "def-public.RuleDefinitionProps.filteredRuleTypes", + "type": "Array", "tags": [], - "label": "showIntervalWarning", + "label": "filteredRuleTypes", "description": [], "signature": [ - "boolean | undefined" + "string[] | undefined" ], "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false @@ -4268,35 +4173,27 @@ }, { "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleStatus", + "id": "def-public.RulesListVisibleColumns", "type": "Type", "tags": [], - "label": "RuleStatus", + "label": "RulesListVisibleColumns", "description": [], "signature": [ - "\"disabled\" | \"enabled\" | \"snoozed\"" + "\"ruleName\" | \"ruleTags\" | \"ruleExecutionStatusLastDate\" | \"ruleSnoozeNotify\" | \"ruleScheduleInterval\" | \"ruleExecutionStatusLastDuration\" | \"ruleExecutionPercentile\" | \"ruleExecutionSuccessRatio\" | \"ruleExecutionStatus\" | \"ruleExecutionState\"" ], - "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "path": "x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_column_selector.tsx", "deprecated": false, "initialIsOpen": false }, { "parentPluginId": "triggersActionsUi", - "id": "def-public.RuleTypeIndex", + "id": "def-public.RuleStatus", "type": "Type", "tags": [], - "label": "RuleTypeIndex", + "label": "RuleStatus", "description": [], "signature": [ - "Map>" + "\"disabled\" | \"enabled\" | \"snoozed\"" ], "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false, @@ -5772,30 +5669,28 @@ }, { "parentPluginId": "triggersActionsUi", - "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRulesListNotifyBadge", + "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRulesList", "type": "Function", "tags": [], - "label": "getRulesListNotifyBadge", + "label": "getRulesList", "description": [], "signature": [ "(props: ", - "RulesListNotifyBadgeProps", - ") => React.ReactElement<", - "RulesListNotifyBadgeProps", - ", string | React.JSXElementConstructor>" + "RulesListProps", + ") => React.ReactElement>" ], "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", "deprecated": false, "children": [ { "parentPluginId": "triggersActionsUi", - "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRulesListNotifyBadge.$1", + "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRulesList.$1", "type": "Object", "tags": [], "label": "props", "description": [], "signature": [ - "RulesListNotifyBadgeProps" + "RulesListProps" ], "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", "deprecated": false, @@ -5806,17 +5701,36 @@ }, { "parentPluginId": "triggersActionsUi", - "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRulesList", + "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRulesListNotifyBadge", "type": "Function", "tags": [], - "label": "getRulesList", + "label": "getRulesListNotifyBadge", "description": [], "signature": [ - "() => React.ReactElement>" + "(props: ", + "RulesListNotifyBadgeProps", + ") => React.ReactElement<", + "RulesListNotifyBadgeProps", + ", string | React.JSXElementConstructor>" ], "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", "deprecated": false, - "children": [], + "children": [ + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.TriggersAndActionsUIPublicPluginStart.getRulesListNotifyBadge.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "RulesListNotifyBadgeProps" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/plugin.ts", + "deprecated": false, + "isRequired": true + } + ], "returnComment": [] }, { diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index c5522864a1c75..7250ffd3d26c9 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github summary: API docs for the triggersActionsUi plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] warning: 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. --- @@ -18,7 +18,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 412 | 0 | 391 | 40 | +| 407 | 0 | 386 | 42 | ## Client diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 49db9908f5e09..eb677005bb8df 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github summary: API docs for the uiActions plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] warning: 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. --- diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 176c8a902aa9c..25def38a93091 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github summary: API docs for the uiActionsEnhanced plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] warning: 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. --- diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 31a4820f9da14..48dba51aca1c0 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github summary: API docs for the unifiedSearch plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] warning: 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. --- diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 40f91935ccaeb..548c288123de6 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github summary: API docs for the unifiedSearch.autocomplete plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] warning: 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. --- diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 257045a1a7cd8..13d621b54a2a3 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github summary: API docs for the urlForwarding plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] warning: 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. --- diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 68a4cf6640fa6..54bc9017f6704 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github summary: API docs for the usageCollection plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] warning: 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. --- diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index c59920507b2c0..467046d89b7de 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github summary: API docs for the ux plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] warning: 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. --- diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 643412cbea7b5..ec5e9751f8f44 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github summary: API docs for the visDefaultEditor plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] warning: 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. --- diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 73b3fd805469b..73fcc40f1d12e 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeGauge plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] warning: 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. --- diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 8fced74534107..c38aebf315312 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeHeatmap plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] warning: 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. --- diff --git a/api_docs/vis_type_pie.devdocs.json b/api_docs/vis_type_pie.devdocs.json index 04d01630e4108..e7612bd29b859 100644 --- a/api_docs/vis_type_pie.devdocs.json +++ b/api_docs/vis_type_pie.devdocs.json @@ -90,7 +90,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; }" ], diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 6f2df2634dae4..d078fa1f79f0f 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypePie plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] warning: 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. --- diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 399fdf3d04609..951b354bcc2b3 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTable plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] warning: 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. --- diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 35ceba01e9d4c..b9356ffd59104 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTimelion plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] warning: 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. --- diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 0e79bc87dad38..8ec9f72bf0837 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeTimeseries plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] warning: 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. --- diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 9c7e5004768fd..9c6072ac8e0c9 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeVega plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] warning: 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. --- diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 63b6b57590f6d..66d593c9342ff 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeVislib plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] warning: 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. --- diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 7ddcc5d5423f9..36ada42dd4d54 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github summary: API docs for the visTypeXy plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] warning: 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. --- diff --git a/api_docs/visualizations.devdocs.json b/api_docs/visualizations.devdocs.json index 07a10571b64cb..d647aaa69542f 100644 --- a/api_docs/visualizations.devdocs.json +++ b/api_docs/visualizations.devdocs.json @@ -1306,7 +1306,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; source?: string | undefined; sourceParams?: ", "SerializableRecord", @@ -4919,7 +4919,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", ">; }" ], @@ -6104,7 +6104,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined) => { id?: string | undefined; params?: Record | undefined; } | undefined" ], @@ -6168,7 +6168,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined" ], @@ -6267,7 +6267,7 @@ "section": "def-common.SerializedFieldFormat", "text": "SerializedFieldFormat" }, - "<", + "<{}, ", "SerializableRecord", "> | undefined; source?: string | undefined; sourceParams?: ", "SerializableRecord", diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 13b8faa002999..a7af86feac5f8 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -4,7 +4,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github summary: API docs for the visualizations plugin -date: 2022-07-13 +date: 2022-07-18 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] warning: 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. --- diff --git a/docs/api/cases/cases-api-get-case.asciidoc b/docs/api/cases/cases-api-get-case.asciidoc index 70cc7f5bab60c..d7bc316a7346d 100644 --- a/docs/api/cases/cases-api-get-case.asciidoc +++ b/docs/api/cases/cases-api-get-case.asciidoc @@ -4,7 +4,7 @@ Get case ++++ -Returns a specified case. +Returns information about a case. === {api-request-title} @@ -17,7 +17,7 @@ Returns a specified case. You must have `read` privileges for the *Cases* feature in the *Management*, *{observability}*, or *Security* section of the <>, depending on the -`owner` of the cases you're seeking. +`owner` of the case you're seeking. === {api-path-parms-title} @@ -42,11 +42,11 @@ default space is used. === {api-examples-title} -Returns case ID `a18b38a0-71b0-11ea-a0b2-c51ea50a58e2` without comments: +Returns case ID `31cdada0-02c1-11ed-85f2-4f7c222ca2fa`: [source,sh] -------------------------------------------------- -GET api/cases/a18b38a0-71b0-11ea-a0b2-c51ea50a58e2 +GET api/cases/31cdada0-02c1-11ed-85f2-4f7c222ca2fa -------------------------------------------------- // KIBANA @@ -55,49 +55,39 @@ The API returns a JSON object with the retrieved case. For example: [source,json] -------------------------------------------------- { - "id": "a18b38a0-71b0-11ea-a0b2-c51ea50a58e2", - "version": "Wzk4LDFd", - "comments": [], - "totalComment": 0, - "totalAlerts": 0, - "closed_at": null, - "closed_by": null, - "created_at": "2020-03-29T11:30:02.658Z", - "created_by": { - "email": "ahunley@imf.usa.gov", - "full_name": "Alan Hunley", - "username": "ahunley" - }, - "external_service": null, - "updated_at": "2020-03-29T12:01:50.244Z", - "updated_by": { - "full_name": "Classified", - "email": "classified@hms.oo.gov.uk", - "username": "M" - }, - "description": "James Bond clicked on a highly suspicious email banner advertising cheap holidays for underpaid civil servants. Operation bubblegum is active. Repeat - operation bubblegum is now active!", - "title": "This case will self-destruct in 5 seconds", - "status": "open", - "connector": { - "id": "131d4448-abe0-4789-939d-8ef60680b498", - "name": "My connector", - "type": ".jira", - "fields": { - "issueType": "10006", - "priority": "High", - } - }, - "settings": { - "syncAlerts": true - }, - "owner": "securitySolution", - "severity": "low", - "duration": null, <1> - "tags": [ - "phishing", - "social engineering", - "bubblegum" - ] + "id":"31cdada0-02c1-11ed-85f2-4f7c222ca2fa", + "version":"WzM2LDFd", + "comments":[{ + "id":"2134c1d0-02c2-11ed-85f2-4f7c222ca2fa", + "version":"WzM3LDFd", + "type":"user", + "owner":"cases", + "comment":"A new comment", + "created_at":"2022-07-13T15:40:32.335Z", + "created_by":{"email":null,"full_name":null,"username":"elastic"}, + "pushed_at":null, + "pushed_by":null, + "updated_at":null, + "updated_by":null + }], + "totalComment":1, + "totalAlerts":0, + "title":"Case title 1", + "tags":["tag 1"], + "settings":{"syncAlerts":true}, + "owner":"cases", + "description":"A case description", + "duration":null, <1> + "severity":"low", + "closed_at":null, + "closed_by":null, + "created_at":"2022-07-13T15:33:50.604Z", + "created_by":{"username":"elastic","email":null,"full_name":null}, + "status":"open", + "updated_at":"2022-07-13T15:40:32.335Z", + "updated_by":{"full_name":null,"email":null,"username":"elastic"}, + "connector":{"id":"none","name":"none","type":".none","fields":null}, + "external_service":null } -------------------------------------------------- <1> Duration represents the elapsed time from the creation of the case to its diff --git a/docs/apm/correlations.asciidoc b/docs/apm/correlations.asciidoc index cb72a1b305fd7..ca77c6c8c6afb 100644 --- a/docs/apm/correlations.asciidoc +++ b/docs/apm/correlations.asciidoc @@ -21,7 +21,7 @@ NOTE: Queries within the {apm-app} are also applied to the correlations. ==== Find high transaction latency correlations The correlations on the *Latency correlations* tab help you discover which -attributes are contributing to increased transaction latency. +attributes are contributing to increased transaction latency. [role="screenshot"] image::apm/images/correlations-hover.png[Latency correlations] @@ -74,7 +74,7 @@ The table is sorted by scores, which are mapped to high, medium, or low impact levels. Attributes with high impact levels are more likely to contribute to failed transactions. By default, the attribute with the highest score is added to the chart. To see a different attribute in the chart, select its row in the -table. +table. For example, in the screenshot below, there are attributes such as a specific node and pod name that have medium impact on the failed transactions. @@ -86,4 +86,4 @@ Select the `+` filter to create a new query in the {apm-app} for transactions with one or more of these attributes. If you are unfamiliar with a field, click the icon beside its name to view its most popular values and optionally filter on those values too. Each time that you add another attribute, it is filtering -out more and more noise and bringing you closer to a diagnosis. \ No newline at end of file +out more and more noise and bringing you closer to a diagnosis. diff --git a/docs/apm/how-to-guides.asciidoc b/docs/apm/how-to-guides.asciidoc index b634c937588b0..88b331de2acf2 100644 --- a/docs/apm/how-to-guides.asciidoc +++ b/docs/apm/how-to-guides.asciidoc @@ -12,6 +12,7 @@ Learn how to perform common APM app tasks. * <> * <> * <> +* <> * <> * <> @@ -30,6 +31,8 @@ include::correlations.asciidoc[] include::machine-learning.asciidoc[] +include::lambda.asciidoc[] + include::advanced-queries.asciidoc[] include::deployment-annotations.asciidoc[] \ No newline at end of file diff --git a/docs/apm/images/lambda-cold-start-trace.png b/docs/apm/images/lambda-cold-start-trace.png new file mode 100644 index 0000000000000..c6f6efd0557ce Binary files /dev/null and b/docs/apm/images/lambda-cold-start-trace.png differ diff --git a/docs/apm/images/lambda-cold-start.png b/docs/apm/images/lambda-cold-start.png new file mode 100644 index 0000000000000..54c3d36fddc64 Binary files /dev/null and b/docs/apm/images/lambda-cold-start.png differ diff --git a/docs/apm/images/lambda-correlations.png b/docs/apm/images/lambda-correlations.png new file mode 100644 index 0000000000000..c1a72ccb2d930 Binary files /dev/null and b/docs/apm/images/lambda-correlations.png differ diff --git a/docs/apm/lambda.asciidoc b/docs/apm/lambda.asciidoc new file mode 100644 index 0000000000000..2dcdf5b462b63 --- /dev/null +++ b/docs/apm/lambda.asciidoc @@ -0,0 +1,51 @@ +[role="xpack"] +[[apm-lambda]] +=== Observe Lambda functions + +Elastic APM provides performance and error monitoring for AWS Lambda functions. +Get insight into function execution and runtime behavior, as well as visibility into how your Lambda functions relate to and depend on other services. + +To set up Lambda monitoring, see the relevant +{apm-guide-ref}/monitoring-aws-lambda.html[quick start guide]. + +[float] +[[apm-lambda-cold-start-info]] +==== Cold starts + +A cold start occurs when a Lambda function has not been used for a certain period of time. A lambda worker receives a request to run the function and prepares an execution environment. + +Cold starts are an unavoidable byproduct of the serverless world, but visibility into how they impact your services can help you make better decisions about factors like how much memory to allocate to a function, whether to enable provisioned concurrency, or if it's time to consider removing a large dependency. + +[float] +[[apm-lambda-cold-start-rate]] +===== Cold start rate + +The cold start rate (i.e. proportion of requests that experience a cold start) is displayed per service and per transaction. + +[role="screenshot"] +image::apm/images/lambda-cold-start.png[lambda cold start graph] + +Cold start is also displayed in the trace waterfall, where you can drill-down into individual traces and see trace metadata like AWS request ID, trigger type, and trigger request ID. + +[role="screenshot"] +image::apm/images/lambda-cold-start-trace.png[lambda cold start trace] + +[float] +[[apm-lambda-cold-start-latency]] +===== Latency distribution correlation + +The <> feature can be used to visualize the impact of Lambda cold starts on latency--just select the `faas.coldstart` field. + +[role="screenshot"] +image::apm/images/lambda-correlations.png[lambda correlations example] + +[float] +[[apm-lambda-service-config]] +==== AWS Lambda function grouping + +The default APM agent configuration results in one APM service per AWS Lambda function, +where the Lambda function name is the service name. + +In some use cases, it makes more sense to logically group multiple lambda functions under a single +APM service. You can achieve this by setting the `ELASTIC_APM_SERVICE_NAME` environment variable +on related Lambda functions to the same value. diff --git a/docs/apm/service-overview.asciidoc b/docs/apm/service-overview.asciidoc index 22da9a132b4fa..eaf022cee8c74 100644 --- a/docs/apm/service-overview.asciidoc +++ b/docs/apm/service-overview.asciidoc @@ -8,7 +8,8 @@ high-level visibility into how a service is performing across your infrastructur * Service details like service version, runtime version, framework, and agent name and version * Container and orchestration information -* Cloud provider, machine type, and availability zone +* Cloud provider, machine type, service name, region, and availability zone +* Serverless function names and event trigger type * Latency, throughput, and errors over time * Service dependencies @@ -16,10 +17,10 @@ high-level visibility into how a service is performing across your infrastructur [[service-time-comparison]] === Time series and expected bounds comparison -For insight into the health of your services, you can compare how a service -performs relative to a previous time frame or to the expected bounds from the -corresponding {anomaly-job}. For example, has latency been slowly increasing -over time, did the service experience a sudden spike, is the throughput similar +For insight into the health of your services, you can compare how a service +performs relative to a previous time frame or to the expected bounds from the +corresponding {anomaly-job}. For example, has latency been slowly increasing +over time, did the service experience a sudden spike, is the throughput similar to what the {ml} job expects – enabling a comparison can provide the answer. [role="screenshot"] @@ -42,8 +43,8 @@ The time-based comparison options are based on the selected time filter range: |An identical amount of time immediately before the selected time range |==== -You can use the expected bounds comparison if {ml-jobs} exist in your selected -environment and you have +You can use the expected bounds comparison if {ml-jobs} exist in your selected +environment and you have {ml-docs}/setup.html#kib-visibility-spaces[access to the {ml-features}]. [discrete] @@ -79,7 +80,7 @@ image::apm/images/traffic-transactions.png[Traffic and transactions] The failed transaction rate represents the percentage of failed transactions from the perspective of the selected service. It's useful for visualizing unexpected increases, decreases, or irregular patterns in a service's transactions. -+ + [TIP] ==== HTTP **transactions** from the HTTP server perspective do not consider a `4xx` status code (client error) as a failure @@ -119,6 +120,17 @@ requires an agent version ≥ v5.6.3. [role="screenshot"] image::apm/images/spans-dependencies.png[Span type duration and dependencies] +[discrete] +[[service-cold-start]] +=== Cold start rate + +The cold start rate chart is specific to serverless services. +It displays the percentage of requests that trigger a cold start of a serverless function. +See <> for more information. + +[role="screenshot"] +image::apm/images/lambda-cold-start.png[lambda cold start graph] + [discrete] [[service-instances]] === Instances @@ -157,9 +169,16 @@ image::apm/images/metadata-icons.png[Service metadata] *Cloud provider information* * Cloud provider +* Cloud service name * Availability zones * Machine types * Project ID +* Region + +*Serverless information* + +* Function name(s) +* Event trigger type *Alerts* diff --git a/docs/apm/transactions.asciidoc b/docs/apm/transactions.asciidoc index e8c5d6600c0bd..8a0cc75bf0c62 100644 --- a/docs/apm/transactions.asciidoc +++ b/docs/apm/transactions.asciidoc @@ -8,7 +8,7 @@ APM agents automatically collect performance metrics on HTTP requests, database [role="screenshot"] image::apm/images/apm-transactions-overview.png[Example view of transactions table in the APM app in Kibana] -The *Latency*, *transactions per minute*, *Failed transaction rate*, and *Average duration by span type* +The *Latency*, *Throughput*, *Failed transaction rate*, *Average duration by span type*, and *Cold start rate* charts display information on all transactions associated with the selected service: *Latency*:: @@ -48,6 +48,10 @@ This could be a sign that the agent does not have auto-instrumentation for whate + It's important to note that if you have asynchronous spans, the sum of all span times may exceed the duration of the transaction. +*Cold start rate*:: +Only applicable to serverless transactions, this chart displays the percentage of requests that trigger a cold start of a serverless function. +See <> for more information. + [discrete] [[transactions-table]] === Transactions table @@ -149,6 +153,7 @@ Learn more about a trace sample in the *Metadata* tab: * Agent information * URL * User - Requires additional configuration, but allows you to see which user experienced the current transaction. +* FaaS information, like cold start, AWS request ID, trigger type, and trigger request ID TIP: All of this data is stored in documents in Elasticsearch. This means you can select "Actions - View transaction in Discover" to see the actual Elasticsearch document under the discover tab. diff --git a/docs/maps/images/enable_filter_by_map_extent.png b/docs/maps/images/enable_filter_by_map_extent.png deleted file mode 100644 index 5132dc8f73dbe..0000000000000 Binary files a/docs/maps/images/enable_filter_by_map_extent.png and /dev/null differ diff --git a/docs/maps/search.asciidoc b/docs/maps/search.asciidoc index 2330bf52abc29..aa747611bdbaa 100644 --- a/docs/maps/search.asciidoc +++ b/docs/maps/search.asciidoc @@ -81,22 +81,17 @@ Create filters from your map to focus in on just the data you want. *Maps* provi [float] [[maps-map-extent-filter]] -==== Filter dashboard by map extent +==== Filter dashboard by map bounds -A map extent shows uniform data across all panels. -As you pan and zoom your map, all panels will update to only include data that is visible in your map. +To filter your dashboard by your map bounds as you pan and zoom your map: -To enable filtering your dashboard by map extent: - -* Open the main menu, and then click *Dashboard*. -* Select your dashboard from the list or click *Create dashboard*. -* If your dashboard does not have a map, add a map panel. -* Click the gear icon image:maps/images/gear_icon.png[gear icon] to open the map panel menu. -* Select *More* to view all panel options. -* Select *Enable filter by map extent*. - -[role="screenshot"] -image::maps/images/enable_filter_by_map_extent.png[] +. Open the main menu, and then click *Dashboard*. +. Select your dashboard from the list or click *Create dashboard*. +. If your dashboard does not have a map, add a map panel. +. Click the gear icon image:maps/images/gear_icon.png[gear icon] to open the map panel menu. +. Select *More* to view all panel options. +. Select *Filter dashboard by map bounds*. +. Select the checkbox for your map panel. [float] [[maps-spatial-filters]] diff --git a/examples/field_formats_example/public/examples/3_creating_custom_format_editor.tsx b/examples/field_formats_example/public/examples/3_creating_custom_format_editor.tsx index 037063b042ce9..3239839ba1338 100644 --- a/examples/field_formats_example/public/examples/3_creating_custom_format_editor.tsx +++ b/examples/field_formats_example/public/examples/3_creating_custom_format_editor.tsx @@ -41,12 +41,12 @@ const ExampleCurrencyFormatEditor: FieldFormatEditor<{ currency: string }> = (pr ExampleCurrencyFormatEditor.formatId = ExampleCurrencyFormat.id; // 3. Wrap editor component in a factory. This is needed to support and encourage code-splitting. -const ExampleCurrencyFormatEditorFactory: FieldFormatEditorFactory<{ - currency: string; -}> = async () => ExampleCurrencyFormatEditor; +const ExampleCurrencyFormatEditorFactory = async () => ExampleCurrencyFormatEditor; ExampleCurrencyFormatEditorFactory.formatId = ExampleCurrencyFormatEditor.formatId; export function registerExampleFormatEditor(indexPatternFieldEditor: IndexPatternFieldEditorSetup) { // 4. Register a field editor. This should happen in setup plugin lifecycle phase. - indexPatternFieldEditor.fieldFormatEditors.register(ExampleCurrencyFormatEditorFactory); + indexPatternFieldEditor.fieldFormatEditors.register( + ExampleCurrencyFormatEditorFactory as FieldFormatEditorFactory + ); } diff --git a/package.json b/package.json index addd2cde108fb..4f98a16e13959 100644 --- a/package.json +++ b/package.json @@ -120,6 +120,7 @@ "@emotion/css": "^11.9.0", "@emotion/react": "^11.9.0", "@emotion/serialize": "^1.0.3", + "@grpc/grpc-js": "^1.6.7", "@hapi/accept": "^5.0.2", "@hapi/boom": "^9.1.4", "@hapi/cookie": "^11.0.2", @@ -158,6 +159,10 @@ "@kbn/core-base-server-mocks": "link:bazel-bin/packages/core/base/core-base-server-mocks", "@kbn/core-config-server-internal": "link:bazel-bin/packages/core/config/core-config-server-internal", "@kbn/core-config-server-mocks": "link:bazel-bin/packages/core/config/core-config-server-mocks", + "@kbn/core-deprecations-browser": "link:bazel-bin/packages/core/deprecations/core-deprecations-browser", + "@kbn/core-deprecations-browser-internal": "link:bazel-bin/packages/core/deprecations/core-deprecations-browser-internal", + "@kbn/core-deprecations-browser-mocks": "link:bazel-bin/packages/core/deprecations/core-deprecations-browser-mocks", + "@kbn/core-deprecations-common": "link:bazel-bin/packages/core/deprecations/core-deprecations-common", "@kbn/core-doc-links-browser": "link:bazel-bin/packages/core/doc-links/core-doc-links-browser", "@kbn/core-doc-links-browser-internal": "link:bazel-bin/packages/core/doc-links/core-doc-links-browser-internal", "@kbn/core-doc-links-browser-mocks": "link:bazel-bin/packages/core/doc-links/core-doc-links-browser-mocks", @@ -203,9 +208,14 @@ "@kbn/core-preboot-server": "link:bazel-bin/packages/core/preboot/core-preboot-server", "@kbn/core-preboot-server-internal": "link:bazel-bin/packages/core/preboot/core-preboot-server-internal", "@kbn/core-preboot-server-mocks": "link:bazel-bin/packages/core/preboot/core-preboot-server-mocks", + "@kbn/core-test-helpers-http-setup-browser": "link:bazel-bin/packages/core/test-helpers/core-test-helpers-http-setup-browser", "@kbn/core-theme-browser": "link:bazel-bin/packages/core/theme/core-theme-browser", "@kbn/core-theme-browser-internal": "link:bazel-bin/packages/core/theme/core-theme-browser-internal", "@kbn/core-theme-browser-mocks": "link:bazel-bin/packages/core/theme/core-theme-browser-mocks", + "@kbn/core-ui-settings-browser": "link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser", + "@kbn/core-ui-settings-browser-internal": "link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser-internal", + "@kbn/core-ui-settings-browser-mocks": "link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser-mocks", + "@kbn/core-ui-settings-common": "link:bazel-bin/packages/core/ui-settings/core-ui-settings-common", "@kbn/crypto": "link:bazel-bin/packages/kbn-crypto", "@kbn/crypto-browser": "link:bazel-bin/packages/kbn-crypto-browser", "@kbn/datemath": "link:bazel-bin/packages/kbn-datemath", @@ -280,6 +290,13 @@ "@mapbox/mapbox-gl-draw": "1.3.0", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mapbox/vector-tile": "1.3.1", + "@opentelemetry/api": "^1.1.0", + "@opentelemetry/api-metrics": "^0.30.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "^0.30.0", + "@opentelemetry/exporter-prometheus": "^0.30.0", + "@opentelemetry/resources": "^1.4.0", + "@opentelemetry/sdk-metrics-base": "^0.30.0", + "@opentelemetry/semantic-conventions": "^1.4.0", "@reduxjs/toolkit": "^1.6.1", "@slack/webhook": "^5.0.4", "@turf/along": "6.0.1", @@ -395,7 +412,7 @@ "minimatch": "^3.1.2", "moment": "^2.29.4", "moment-duration-format": "^2.3.2", - "moment-timezone": "^0.5.27", + "moment-timezone": "^0.5.34", "monaco-editor": "^0.22.3", "mustache": "^2.3.2", "node-fetch": "^2.6.7", @@ -597,8 +614,6 @@ "@kbn/type-summarizer-core": "link:bazel-bin/packages/kbn-type-summarizer-core", "@loaders.gl/polyfills": "^2.3.5", "@mapbox/vector-tile": "1.3.1", - "@microsoft/api-documenter": "7.13.68", - "@microsoft/api-extractor": "7.18.19", "@octokit/rest": "^16.35.0", "@openpgp/web-stream-tools": "^0.0.10", "@percy/agent": "^0.28.6", @@ -730,6 +745,10 @@ "@types/kbn__core-common-internal-base": "link:bazel-bin/packages/core/common/internal-base/npm_module_types", "@types/kbn__core-config-server-internal": "link:bazel-bin/packages/core/config/core-config-server-internal/npm_module_types", "@types/kbn__core-config-server-mocks": "link:bazel-bin/packages/core/config/core-config-server-mocks/npm_module_types", + "@types/kbn__core-deprecations-browser": "link:bazel-bin/packages/core/deprecations/core-deprecations-browser/npm_module_types", + "@types/kbn__core-deprecations-browser-internal": "link:bazel-bin/packages/core/deprecations/core-deprecations-browser-internal/npm_module_types", + "@types/kbn__core-deprecations-browser-mocks": "link:bazel-bin/packages/core/deprecations/core-deprecations-browser-mocks/npm_module_types", + "@types/kbn__core-deprecations-common": "link:bazel-bin/packages/core/deprecations/core-deprecations-common/npm_module_types", "@types/kbn__core-doc-links-browser": "link:bazel-bin/packages/core/doc-links/core-doc-links-browser/npm_module_types", "@types/kbn__core-doc-links-browser-internal": "link:bazel-bin/packages/core/doc-links/core-doc-links-browser-internal/npm_module_types", "@types/kbn__core-doc-links-browser-mocks": "link:bazel-bin/packages/core/doc-links/core-doc-links-browser-mocks/npm_module_types", @@ -777,9 +796,14 @@ "@types/kbn__core-preboot-server-mocks": "link:bazel-bin/packages/core/preboot/core-preboot-server-mocks/npm_module_types", "@types/kbn__core-public-internal-base": "link:bazel-bin/packages/core/public/internal-base/npm_module_types", "@types/kbn__core-server-internal-base": "link:bazel-bin/packages/core/server/internal-base/npm_module_types", + "@types/kbn__core-test-helpers-http-setup-browser": "link:bazel-bin/packages/core/test-helpers/core-test-helpers-http-setup-browser/npm_module_types", "@types/kbn__core-theme-browser": "link:bazel-bin/packages/core/theme/core-theme-browser/npm_module_types", "@types/kbn__core-theme-browser-internal": "link:bazel-bin/packages/core/theme/core-theme-browser-internal/npm_module_types", "@types/kbn__core-theme-browser-mocks": "link:bazel-bin/packages/core/theme/core-theme-browser-mocks/npm_module_types", + "@types/kbn__core-ui-settings-browser": "link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser/npm_module_types", + "@types/kbn__core-ui-settings-browser-internal": "link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser-internal/npm_module_types", + "@types/kbn__core-ui-settings-browser-mocks": "link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser-mocks/npm_module_types", + "@types/kbn__core-ui-settings-common": "link:bazel-bin/packages/core/ui-settings/core-ui-settings-common/npm_module_types", "@types/kbn__crypto": "link:bazel-bin/packages/kbn-crypto/npm_module_types", "@types/kbn__crypto-browser": "link:bazel-bin/packages/kbn-crypto-browser/npm_module_types", "@types/kbn__datemath": "link:bazel-bin/packages/kbn-datemath/npm_module_types", @@ -887,7 +911,7 @@ "@types/mocha": "^9.1.1", "@types/mock-fs": "^4.13.1", "@types/moment-duration-format": "^2.2.3", - "@types/moment-timezone": "^0.5.12", + "@types/moment-timezone": "^0.5.30", "@types/mustache": "^0.8.31", "@types/ncp": "^2.0.1", "@types/nock": "^10.0.3", @@ -1050,7 +1074,7 @@ "has-ansi": "^3.0.0", "hdr-histogram-js": "^1.2.0", "html": "1.0.0", - "html-loader": "^0.5.5", + "html-loader": "^1.3.2", "http-proxy": "^1.18.1", "is-glob": "^4.0.1", "is-path-inside": "^3.0.2", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index 8d39cf240970b..fb1f7a6bdb146 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -27,6 +27,10 @@ filegroup( "//packages/core/base/core-base-server-internal:build", "//packages/core/base/core-base-server-mocks:build", "//packages/core/config/core-config-server-internal:build", + "//packages/core/deprecations/core-deprecations-browser-internal:build", + "//packages/core/deprecations/core-deprecations-browser-mocks:build", + "//packages/core/deprecations/core-deprecations-browser:build", + "//packages/core/deprecations/core-deprecations-common:build", "//packages/core/doc-links/core-doc-links-browser-internal:build", "//packages/core/doc-links/core-doc-links-browser-mocks:build", "//packages/core/doc-links/core-doc-links-browser:build", @@ -72,9 +76,14 @@ filegroup( "//packages/core/preboot/core-preboot-server-internal:build", "//packages/core/preboot/core-preboot-server-mocks:build", "//packages/core/preboot/core-preboot-server:build", + "//packages/core/test-helpers/core-test-helpers-http-setup-browser:build", "//packages/core/theme/core-theme-browser-internal:build", "//packages/core/theme/core-theme-browser-mocks:build", "//packages/core/theme/core-theme-browser:build", + "//packages/core/ui-settings/core-ui-settings-browser-internal:build", + "//packages/core/ui-settings/core-ui-settings-browser-mocks:build", + "//packages/core/ui-settings/core-ui-settings-browser:build", + "//packages/core/ui-settings/core-ui-settings-common:build", "//packages/elastic-apm-synthtrace:build", "//packages/elastic-safer-lodash-set:build", "//packages/home/sample_data_cards:build", @@ -224,6 +233,10 @@ filegroup( "//packages/core/base/core-base-server-internal:build_types", "//packages/core/base/core-base-server-mocks:build_types", "//packages/core/config/core-config-server-internal:build_types", + "//packages/core/deprecations/core-deprecations-browser-internal:build_types", + "//packages/core/deprecations/core-deprecations-browser-mocks:build_types", + "//packages/core/deprecations/core-deprecations-browser:build_types", + "//packages/core/deprecations/core-deprecations-common:build_types", "//packages/core/doc-links/core-doc-links-browser-internal:build_types", "//packages/core/doc-links/core-doc-links-browser-mocks:build_types", "//packages/core/doc-links/core-doc-links-browser:build_types", @@ -269,9 +282,14 @@ filegroup( "//packages/core/preboot/core-preboot-server-internal:build_types", "//packages/core/preboot/core-preboot-server-mocks:build_types", "//packages/core/preboot/core-preboot-server:build_types", + "//packages/core/test-helpers/core-test-helpers-http-setup-browser:build_types", "//packages/core/theme/core-theme-browser-internal:build_types", "//packages/core/theme/core-theme-browser-mocks:build_types", "//packages/core/theme/core-theme-browser:build_types", + "//packages/core/ui-settings/core-ui-settings-browser-internal:build_types", + "//packages/core/ui-settings/core-ui-settings-browser-mocks:build_types", + "//packages/core/ui-settings/core-ui-settings-browser:build_types", + "//packages/core/ui-settings/core-ui-settings-common:build_types", "//packages/elastic-apm-synthtrace:build_types", "//packages/elastic-safer-lodash-set:build_types", "//packages/home/sample_data_cards:build_types", diff --git a/packages/core/deprecations/core-deprecations-browser-internal/BUILD.bazel b/packages/core/deprecations/core-deprecations-browser-internal/BUILD.bazel new file mode 100644 index 0000000000000..c3f2e0f4c1a23 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-internal/BUILD.bazel @@ -0,0 +1,114 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-deprecations-browser-internal" +PKG_REQUIRE_NAME = "@kbn/core-deprecations-browser-internal" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "//packages/kbn-i18n", + "//packages/core/http/core-http-browser-mocks", +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/react", + "//packages/kbn-i18n:npm_module_types", + "//packages/core/base/core-base-browser-internal:npm_module_types", + "//packages/core/http/core-http-browser:npm_module_types", + "//packages/core/http/core-http-browser-mocks:npm_module_types", + "//packages/core/deprecations/core-deprecations-common:npm_module_types", + "//packages/core/deprecations/core-deprecations-browser:npm_module_types" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/deprecations/core-deprecations-browser-internal/README.md b/packages/core/deprecations/core-deprecations-browser-internal/README.md new file mode 100644 index 0000000000000..8f7b2f147deaf --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-internal/README.md @@ -0,0 +1,3 @@ +# @kbn/core-deprecations-browser-internal + +Contains implementation and internal types for Core's client-side `deprecations` service diff --git a/packages/core/deprecations/core-deprecations-browser-internal/jest.config.js b/packages/core/deprecations/core-deprecations-browser-internal/jest.config.js new file mode 100644 index 0000000000000..c1baf6d1fdfc9 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-internal/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/deprecations/core-deprecations-browser-internal'], +}; diff --git a/packages/core/deprecations/core-deprecations-browser-internal/package.json b/packages/core/deprecations/core-deprecations-browser-internal/package.json new file mode 100644 index 0000000000000..1f4a5d5531ce9 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-internal/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-deprecations-browser-internal", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/public/deprecations/deprecations_client.test.ts b/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_client.test.ts similarity index 98% rename from src/core/public/deprecations/deprecations_client.test.ts rename to packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_client.test.ts index 7bff04cccf323..49d9c0a23956a 100644 --- a/src/core/public/deprecations/deprecations_client.test.ts +++ b/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_client.test.ts @@ -8,7 +8,7 @@ import { httpServiceMock } from '@kbn/core-http-browser-mocks'; import { DeprecationsClient } from './deprecations_client'; -import type { DomainDeprecationDetails } from '../../server/types'; +import type { DomainDeprecationDetails } from '@kbn/core-deprecations-common'; describe('DeprecationsClient', () => { const http = httpServiceMock.createSetupContract(); diff --git a/src/core/public/deprecations/deprecations_client.ts b/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_client.ts similarity index 92% rename from src/core/public/deprecations/deprecations_client.ts rename to packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_client.ts index 80b1913fcfaf1..f3f2bd7f28e8a 100644 --- a/src/core/public/deprecations/deprecations_client.ts +++ b/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_client.ts @@ -8,16 +8,17 @@ import { i18n } from '@kbn/i18n'; import type { HttpStart } from '@kbn/core-http-browser'; -import type { DomainDeprecationDetails, DeprecationsGetResponse } from '../../server/types'; +import type { + DomainDeprecationDetails, + DeprecationsGetResponse, +} from '@kbn/core-deprecations-common'; +import type { ResolveDeprecationResponse } from '@kbn/core-deprecations-browser'; /* @internal */ export interface DeprecationsClientDeps { http: Pick; } -/* @internal */ -export type ResolveDeprecationResponse = { status: 'ok' } | { status: 'fail'; reason: string }; - export class DeprecationsClient { private readonly http: Pick; constructor({ http }: DeprecationsClientDeps) { diff --git a/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts b/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts new file mode 100644 index 0000000000000..edaf5f7f27be0 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-internal/src/deprecations_service.ts @@ -0,0 +1,29 @@ +/* + * Copyright 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 { CoreService } from '@kbn/core-base-browser-internal'; +import type { DeprecationsServiceStart } from '@kbn/core-deprecations-browser'; +import type { HttpStart } from '@kbn/core-http-browser'; +import { DeprecationsClient } from './deprecations_client'; + +export class DeprecationsService implements CoreService { + public setup(): void {} + + public start({ http }: { http: HttpStart }): DeprecationsServiceStart { + const deprecationsClient = new DeprecationsClient({ http }); + + return { + getAllDeprecations: deprecationsClient.getAllDeprecations, + getDeprecations: deprecationsClient.getDeprecations, + isDeprecationResolvable: deprecationsClient.isDeprecationResolvable, + resolveDeprecation: deprecationsClient.resolveDeprecation, + }; + } + + public stop(): void {} +} diff --git a/src/core/public/deprecations/index.ts b/packages/core/deprecations/core-deprecations-browser-internal/src/index.ts similarity index 74% rename from src/core/public/deprecations/index.ts rename to packages/core/deprecations/core-deprecations-browser-internal/src/index.ts index 092cbed613ac2..758a941ee3a04 100644 --- a/src/core/public/deprecations/index.ts +++ b/packages/core/deprecations/core-deprecations-browser-internal/src/index.ts @@ -7,5 +7,3 @@ */ export { DeprecationsService } from './deprecations_service'; -export type { DeprecationsServiceStart } from './deprecations_service'; -export type { ResolveDeprecationResponse } from './deprecations_client'; diff --git a/packages/core/deprecations/core-deprecations-browser-internal/tsconfig.json b/packages/core/deprecations/core-deprecations-browser-internal/tsconfig.json new file mode 100644 index 0000000000000..39d3c7097814a --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-internal/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/deprecations/core-deprecations-browser-mocks/BUILD.bazel b/packages/core/deprecations/core-deprecations-browser-mocks/BUILD.bazel new file mode 100644 index 0000000000000..8c840af011078 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-mocks/BUILD.bazel @@ -0,0 +1,110 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-deprecations-browser-mocks" +PKG_REQUIRE_NAME = "@kbn/core-deprecations-browser-mocks" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "//packages/core/deprecations/core-deprecations-browser-internal" +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/react", + "//packages/kbn-utility-types:npm_module_types", + "//packages/core/deprecations/core-deprecations-browser:npm_module_types", + "//packages/core/deprecations/core-deprecations-browser-internal:npm_module_types" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/deprecations/core-deprecations-browser-mocks/README.md b/packages/core/deprecations/core-deprecations-browser-mocks/README.md new file mode 100644 index 0000000000000..a11bbcc144ebb --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-mocks/README.md @@ -0,0 +1,3 @@ +# @kbn/core-deprecations-browser-mocks + +Contains mocks for Core's client-side `deprecations` service diff --git a/packages/core/deprecations/core-deprecations-browser-mocks/jest.config.js b/packages/core/deprecations/core-deprecations-browser-mocks/jest.config.js new file mode 100644 index 0000000000000..4bfb844cf8fa3 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-mocks/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/deprecations/core-deprecations-browser-mocks'], +}; diff --git a/packages/core/deprecations/core-deprecations-browser-mocks/package.json b/packages/core/deprecations/core-deprecations-browser-mocks/package.json new file mode 100644 index 0000000000000..47b5aa1f0add2 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-mocks/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-deprecations-browser-mocks", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/public/deprecations/deprecations_service.mock.ts b/packages/core/deprecations/core-deprecations-browser-mocks/src/deprecations_service.mock.ts similarity index 88% rename from src/core/public/deprecations/deprecations_service.mock.ts rename to packages/core/deprecations/core-deprecations-browser-mocks/src/deprecations_service.mock.ts index 5bcd52982d513..f742f84036ea6 100644 --- a/src/core/public/deprecations/deprecations_service.mock.ts +++ b/packages/core/deprecations/core-deprecations-browser-mocks/src/deprecations_service.mock.ts @@ -7,8 +7,8 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; -import { DeprecationsService } from './deprecations_service'; -import type { DeprecationsServiceStart } from './deprecations_service'; +import { DeprecationsService } from '@kbn/core-deprecations-browser-internal'; +import type { DeprecationsServiceStart } from '@kbn/core-deprecations-browser'; const createServiceMock = (): jest.Mocked => ({ getAllDeprecations: jest.fn().mockResolvedValue([]), diff --git a/packages/core/deprecations/core-deprecations-browser-mocks/src/index.ts b/packages/core/deprecations/core-deprecations-browser-mocks/src/index.ts new file mode 100644 index 0000000000000..1239090c387ad --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-mocks/src/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { deprecationsServiceMock } from './deprecations_service.mock'; diff --git a/packages/core/deprecations/core-deprecations-browser-mocks/tsconfig.json b/packages/core/deprecations/core-deprecations-browser-mocks/tsconfig.json new file mode 100644 index 0000000000000..39d3c7097814a --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser-mocks/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/deprecations/core-deprecations-browser/BUILD.bazel b/packages/core/deprecations/core-deprecations-browser/BUILD.bazel new file mode 100644 index 0000000000000..85a9e6c411c21 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser/BUILD.bazel @@ -0,0 +1,107 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-deprecations-browser" +PKG_REQUIRE_NAME = "@kbn/core-deprecations-browser" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/react", + "//packages/core/deprecations/core-deprecations-common:npm_module_types" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/deprecations/core-deprecations-browser/README.md b/packages/core/deprecations/core-deprecations-browser/README.md new file mode 100644 index 0000000000000..3c7bae6833733 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser/README.md @@ -0,0 +1,3 @@ +# @kbn/core-deprecations-browser + +Contains public types for Core's client-side `deprecations` service diff --git a/packages/core/deprecations/core-deprecations-browser/jest.config.js b/packages/core/deprecations/core-deprecations-browser/jest.config.js new file mode 100644 index 0000000000000..9f08c08e4fb41 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/deprecations/core-deprecations-browser'], +}; diff --git a/packages/core/deprecations/core-deprecations-browser/package.json b/packages/core/deprecations/core-deprecations-browser/package.json new file mode 100644 index 0000000000000..d4e5346ab80a8 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-deprecations-browser", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/public/deprecations/deprecations_service.ts b/packages/core/deprecations/core-deprecations-browser/src/contracts.ts similarity index 60% rename from src/core/public/deprecations/deprecations_service.ts rename to packages/core/deprecations/core-deprecations-browser/src/contracts.ts index bcc701cc634a0..c8e8d08e79848 100644 --- a/src/core/public/deprecations/deprecations_service.ts +++ b/packages/core/deprecations/core-deprecations-browser/src/contracts.ts @@ -5,11 +5,8 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - -import type { CoreService } from '@kbn/core-base-browser-internal'; -import type { HttpStart } from '@kbn/core-http-browser'; -import { DeprecationsClient, ResolveDeprecationResponse } from './deprecations_client'; -import type { DomainDeprecationDetails } from '../../server/types'; +import type { DomainDeprecationDetails } from '@kbn/core-deprecations-common'; +import type { ResolveDeprecationResponse } from './types'; /** * DeprecationsService provides methods to fetch domain deprecation details from @@ -41,20 +38,3 @@ export interface DeprecationsServiceStart { */ resolveDeprecation: (details: DomainDeprecationDetails) => Promise; } - -export class DeprecationsService implements CoreService { - public setup(): void {} - - public start({ http }: { http: HttpStart }): DeprecationsServiceStart { - const deprecationsClient = new DeprecationsClient({ http }); - - return { - getAllDeprecations: deprecationsClient.getAllDeprecations, - getDeprecations: deprecationsClient.getDeprecations, - isDeprecationResolvable: deprecationsClient.isDeprecationResolvable, - resolveDeprecation: deprecationsClient.resolveDeprecation, - }; - } - - public stop(): void {} -} diff --git a/packages/core/deprecations/core-deprecations-browser/src/index.ts b/packages/core/deprecations/core-deprecations-browser/src/index.ts new file mode 100644 index 0000000000000..4ae415ba26f5e --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser/src/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { DeprecationsServiceStart } from './contracts'; +export type { ResolveDeprecationResponse } from './types'; diff --git a/packages/core/deprecations/core-deprecations-browser/src/types.ts b/packages/core/deprecations/core-deprecations-browser/src/types.ts new file mode 100644 index 0000000000000..a51174445edac --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser/src/types.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * Response from correctiveActions.api call from automatically resolving the deprecation + * @public + */ +export type ResolveDeprecationResponse = { status: 'ok' } | { status: 'fail'; reason: string }; diff --git a/packages/core/deprecations/core-deprecations-browser/tsconfig.json b/packages/core/deprecations/core-deprecations-browser/tsconfig.json new file mode 100644 index 0000000000000..39d3c7097814a --- /dev/null +++ b/packages/core/deprecations/core-deprecations-browser/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/deprecations/core-deprecations-common/BUILD.bazel b/packages/core/deprecations/core-deprecations-common/BUILD.bazel new file mode 100644 index 0000000000000..7bddbc3cebaf7 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-common/BUILD.bazel @@ -0,0 +1,106 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-deprecations-common" +PKG_REQUIRE_NAME = "@kbn/core-deprecations-common" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/react" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/deprecations/core-deprecations-common/README.md b/packages/core/deprecations/core-deprecations-common/README.md new file mode 100644 index 0000000000000..503006503c060 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-common/README.md @@ -0,0 +1,3 @@ +# @kbn/core-deprecations-common + +Contains public shared types for Core's `deprecations` service diff --git a/packages/core/deprecations/core-deprecations-common/jest.config.js b/packages/core/deprecations/core-deprecations-common/jest.config.js new file mode 100644 index 0000000000000..3a20374e4f7ad --- /dev/null +++ b/packages/core/deprecations/core-deprecations-common/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/deprecations/core-deprecations-common'], +}; diff --git a/packages/core/deprecations/core-deprecations-common/package.json b/packages/core/deprecations/core-deprecations-common/package.json new file mode 100644 index 0000000000000..66dd322302c60 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-common/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-deprecations-common", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/core/deprecations/core-deprecations-common/src/index.ts b/packages/core/deprecations/core-deprecations-common/src/index.ts new file mode 100644 index 0000000000000..3013ad0f32281 --- /dev/null +++ b/packages/core/deprecations/core-deprecations-common/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { + BaseDeprecationDetails, + ConfigDeprecationDetails, + FeatureDeprecationDetails, + DeprecationsDetails, + DomainDeprecationDetails, + DeprecationsGetResponse, +} from './types'; diff --git a/packages/core/deprecations/core-deprecations-common/src/types.ts b/packages/core/deprecations/core-deprecations-common/src/types.ts new file mode 100644 index 0000000000000..8dc7a08923bad --- /dev/null +++ b/packages/core/deprecations/core-deprecations-common/src/types.ts @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * Base properties shared by all types of deprecations + * + * @public + */ +export interface BaseDeprecationDetails { + /** + * The title of the deprecation. + * Check the README for writing deprecations in `src/core/server/deprecations/README.mdx` + */ + title: string; + /** + * The description message to be displayed for the deprecation. + * Check the README for writing deprecations in `src/core/server/deprecations/README.mdx` + */ + message: string; + /** + * levels: + * - warning: will not break deployment upon upgrade + * - critical: needs to be addressed before upgrade. + * - fetch_error: Deprecations service failed to grab the deprecation details for the domain. + */ + level: 'warning' | 'critical' | 'fetch_error'; + /** + * (optional) Used to identify between different deprecation types. + * Example use case: in Upgrade Assistant, we may want to allow the user to sort by + * deprecation type or show each type in a separate tab. + * + * Feel free to add new types if necessary. + * Predefined types are necessary to reduce having similar definitions with different keywords + * across kibana deprecations. + */ + deprecationType?: 'config' | 'feature'; + /** (optional) link to the documentation for more details on the deprecation. */ + documentationUrl?: string; + /** (optional) specify the fix for this deprecation requires a full kibana restart. */ + requireRestart?: boolean; + /** corrective action needed to fix this deprecation. */ + correctiveActions: { + /** + * (optional) The api to be called to automatically fix the deprecation + * Each domain should implement a POST/PUT route for their plugin to + * handle their deprecations. + */ + api?: { + /** Kibana route path. Passing a query string is allowed */ + path: string; + /** Kibana route method: 'POST' or 'PUT'. */ + method: 'POST' | 'PUT'; + /** Additional details to be passed to the route. */ + body?: { + [key: string]: any; + }; + /* Allow to omit context in the request of the body */ + omitContextFromBody?: boolean; + }; + /** + * Specify a list of manual steps users need to follow to + * fix the deprecation before upgrade. Required even if an API + * corrective action is set in case the API fails. + * Check the README for writing deprecations in `src/core/server/deprecations/README.mdx` + */ + manualSteps: string[]; + }; +} + +/** + * @public + */ +export interface ConfigDeprecationDetails extends BaseDeprecationDetails { + configPath: string; + deprecationType: 'config'; +} + +/** + * @public + */ +export interface FeatureDeprecationDetails extends BaseDeprecationDetails { + deprecationType?: 'feature' | undefined; +} + +/** + * @public + */ +export type DeprecationsDetails = ConfigDeprecationDetails | FeatureDeprecationDetails; + +/** + * @public + */ +export type DomainDeprecationDetails = DeprecationsDetails & { + domainId: string; +}; + +/** + * @public + */ +export interface DeprecationsGetResponse { + deprecations: DomainDeprecationDetails[]; +} diff --git a/packages/core/deprecations/core-deprecations-common/tsconfig.json b/packages/core/deprecations/core-deprecations-common/tsconfig.json new file mode 100644 index 0000000000000..39d3c7097814a --- /dev/null +++ b/packages/core/deprecations/core-deprecations-common/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/logging/core-logging-server-internal/BUILD.bazel b/packages/core/logging/core-logging-server-internal/BUILD.bazel index ea2e1e1550bdf..d5afc20b5e40a 100644 --- a/packages/core/logging/core-logging-server-internal/BUILD.bazel +++ b/packages/core/logging/core-logging-server-internal/BUILD.bazel @@ -31,6 +31,7 @@ RUNTIME_DEPS = [ "@npm//elastic-apm-node", "//packages/elastic-safer-lodash-set", "//packages/kbn-config-schema", + "//packages/kbn-std", ] TYPES_DEPS = [ diff --git a/packages/core/logging/core-logging-server-internal/src/global_context/index.ts b/packages/core/logging/core-logging-server-internal/src/global_context/index.ts new file mode 100644 index 0000000000000..e7a8a0be56c8e --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/src/global_context/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { mergeGlobalContext } from './merge_global_context'; +export type { GlobalContext } from './types'; diff --git a/packages/core/logging/core-logging-server-internal/src/global_context/merge_global_context.test.ts b/packages/core/logging/core-logging-server-internal/src/global_context/merge_global_context.test.ts new file mode 100644 index 0000000000000..63840d3ab3fbc --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/src/global_context/merge_global_context.test.ts @@ -0,0 +1,103 @@ +/* + * Copyright 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 { LogMeta } from '@kbn/logging'; +import { GlobalContext } from './types'; +import { mergeGlobalContext } from './merge_global_context'; + +describe('mergeGlobalContext', () => { + test('inserts global meta in entry meta', () => { + const context: GlobalContext = { + bar: false, + }; + const meta: LogMeta = { + // @ts-expect-error Custom ECS field + foo: true, + }; + + expect(mergeGlobalContext(context, meta)).toEqual({ + foo: true, + bar: false, + }); + }); + + test('handles nested context', () => { + const context: GlobalContext = { + 'bar.baz': false, + }; + const meta: LogMeta = { + // @ts-expect-error Custom ECS field + foo: true, + }; + + expect(mergeGlobalContext(context, meta)).toEqual({ + foo: true, + bar: { baz: false }, + }); + }); + + test('does not overwrite meta with global context if the path already exists', () => { + const context: GlobalContext = { + foo: false, + bar: [false], + }; + const meta: LogMeta = { + // @ts-expect-error Custom ECS field + foo: true, + bar: [true], + }; + + expect(mergeGlobalContext(context, meta)).toEqual({ + foo: true, + bar: [true], + }); + }); + + test('if conflicting entries exist in the context, the most specific entry wins', () => { + const context: GlobalContext = { + 'a.b.c': 'd', + 'a.b': 'c', + }; + + // Note that this "most specific entry wins" behavior should not happen in practice, + // as the `LoggingSystem` is handling deconfliction of paths before anything is + // provided to the `LoggerAdapter` in the first place. Including this test just to + // ensure the actual behavior of this function is documented for posterity. + expect(mergeGlobalContext(context)).toEqual({ + a: { b: { c: 'd' } }, + }); + }); + + test('does nothing if no global meta has been set', () => { + const context: GlobalContext = {}; + const meta: LogMeta = { + // @ts-expect-error Custom ECS field + foo: true, + }; + + expect(mergeGlobalContext(context, meta)).toEqual({ + foo: true, + }); + }); + + test('adds global meta even if no user-provided meta exists', () => { + const context: GlobalContext = { + foo: true, + }; + + expect(mergeGlobalContext(context)).toEqual({ + foo: true, + }); + }); + + test('does nothing if no global meta or user-provided meta has been set', () => { + const context: GlobalContext = {}; + + expect(mergeGlobalContext(context)).toBeUndefined(); + }); +}); diff --git a/packages/core/logging/core-logging-server-internal/src/global_context/merge_global_context.ts b/packages/core/logging/core-logging-server-internal/src/global_context/merge_global_context.ts new file mode 100644 index 0000000000000..64186392caa56 --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/src/global_context/merge_global_context.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { has } from 'lodash'; +import { set } from '@elastic/safer-lodash-set'; +import { LogMeta } from '@kbn/logging'; +import { GlobalContext } from './types'; + +/** + * Takes a flattened object of {@link GlobalContext} and applies it to the + * provided {@link LogMeta}. + * + * @remarks + * The provided `LogMeta` takes precedence over the `GlobalContext`; + * if duplicate keys are found, the `GlobalContext` will be overridden. + * + * @example + * ```ts + * const meta: LogMeta = { + * a: { b: false }, + * d: 'hi', + * }; + * const context: GlobalContext = { + * 'a.b': true, + * c: [1, 2, 3], + * }; + * + * mergeGlobalContext(context, meta); + * // { + * // a: { b: false }, + * // c: [1, 2, 3], + * // d: 'hi', + * // } + * ``` + * + * @internal + */ +export function mergeGlobalContext(globalContext: GlobalContext, meta?: LogMeta) { + if (!meta && Object.keys(globalContext).length === 0) { + return; + } + + const mergedMeta = meta ?? {}; + for (const [path, data] of Object.entries(globalContext)) { + if (!has(mergedMeta, path)) { + set(mergedMeta, path, data); + } + } + + return mergedMeta; +} diff --git a/packages/core/logging/core-logging-server-internal/src/global_context/types.ts b/packages/core/logging/core-logging-server-internal/src/global_context/types.ts new file mode 100644 index 0000000000000..bb377aa14e390 --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/src/global_context/types.ts @@ -0,0 +1,29 @@ +/* + * Copyright 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. + */ + +/** + * A flattened object containing lodash-style dot-separated keys, which + * indicate the path to where each corresponding value should live in a + * nested object. + * + * @remarks + * Arrays are treated as primitives here: array entries should not be broken + * down into separate keys. + * + * @example + * ```ts + * const context: GlobalContext = { + * a: true, + * 'b.c': [1, 2, 3], + * 'd.e.f': 'g', + * }; + * ``` + * + * @internal + */ +export type GlobalContext = Record; diff --git a/packages/core/logging/core-logging-server-internal/src/logger_adapter.test.ts b/packages/core/logging/core-logging-server-internal/src/logger_adapter.test.ts index c7be02e5c0a98..28f747ef3fcf6 100644 --- a/packages/core/logging/core-logging-server-internal/src/logger_adapter.test.ts +++ b/packages/core/logging/core-logging-server-internal/src/logger_adapter.test.ts @@ -7,84 +7,172 @@ */ import type { Logger } from '@kbn/logging'; +import { loggerMock } from '@kbn/logging-mocks'; import { LoggerAdapter } from './logger_adapter'; -test('proxies all method calls to the internal logger.', () => { - const internalLogger: Logger = { - debug: jest.fn(), - error: jest.fn(), - fatal: jest.fn(), - info: jest.fn(), - log: jest.fn(), - trace: jest.fn(), - warn: jest.fn(), - get: jest.fn(), - }; - - const adapter = new LoggerAdapter(internalLogger); - - adapter.trace('trace-message'); - expect(internalLogger.trace).toHaveBeenCalledTimes(1); - expect(internalLogger.trace).toHaveBeenCalledWith('trace-message', undefined); - - adapter.debug('debug-message'); - expect(internalLogger.debug).toHaveBeenCalledTimes(1); - expect(internalLogger.debug).toHaveBeenCalledWith('debug-message', undefined); - - adapter.info('info-message'); - expect(internalLogger.info).toHaveBeenCalledTimes(1); - expect(internalLogger.info).toHaveBeenCalledWith('info-message', undefined); - - adapter.warn('warn-message'); - expect(internalLogger.warn).toHaveBeenCalledTimes(1); - expect(internalLogger.warn).toHaveBeenCalledWith('warn-message', undefined); - - adapter.error('error-message'); - expect(internalLogger.error).toHaveBeenCalledTimes(1); - expect(internalLogger.error).toHaveBeenCalledWith('error-message', undefined); - - adapter.fatal('fatal-message'); - expect(internalLogger.fatal).toHaveBeenCalledTimes(1); - expect(internalLogger.fatal).toHaveBeenCalledWith('fatal-message', undefined); - - adapter.get('context'); - expect(internalLogger.get).toHaveBeenCalledTimes(1); - expect(internalLogger.get).toHaveBeenCalledWith('context'); -}); +describe('LoggerAdapter', () => { + let internalLogger: Logger; + + beforeEach(() => { + internalLogger = loggerMock.create(); + }); + + test('proxies all method calls to the internal logger.', () => { + const adapter = new LoggerAdapter(internalLogger); + + adapter.trace('trace-message'); + expect(internalLogger.trace).toHaveBeenCalledTimes(1); + expect(internalLogger.trace).toHaveBeenCalledWith('trace-message', undefined); + + adapter.debug('debug-message'); + expect(internalLogger.debug).toHaveBeenCalledTimes(1); + expect(internalLogger.debug).toHaveBeenCalledWith('debug-message', undefined); + + adapter.info('info-message'); + expect(internalLogger.info).toHaveBeenCalledTimes(1); + expect(internalLogger.info).toHaveBeenCalledWith('info-message', undefined); + + adapter.warn('warn-message'); + expect(internalLogger.warn).toHaveBeenCalledTimes(1); + expect(internalLogger.warn).toHaveBeenCalledWith('warn-message', undefined); + + adapter.error('error-message'); + expect(internalLogger.error).toHaveBeenCalledTimes(1); + expect(internalLogger.error).toHaveBeenCalledWith('error-message', undefined); + + adapter.fatal('fatal-message'); + expect(internalLogger.fatal).toHaveBeenCalledTimes(1); + expect(internalLogger.fatal).toHaveBeenCalledWith('fatal-message', undefined); + + adapter.get('context'); + expect(internalLogger.get).toHaveBeenCalledTimes(1); + expect(internalLogger.get).toHaveBeenCalledWith('context'); + }); + + test('forwards all method calls to new internal logger if it is updated.', () => { + const newInternalLogger = loggerMock.create(); + + const adapter = new LoggerAdapter(internalLogger); + + adapter.trace('trace-message'); + expect(internalLogger.trace).toHaveBeenCalledTimes(1); + expect(internalLogger.trace).toHaveBeenCalledWith('trace-message', undefined); + (internalLogger.trace as jest.Mock<() => void>).mockReset(); + + adapter.updateLogger(newInternalLogger); + adapter.trace('trace-message'); + expect(internalLogger.trace).not.toHaveBeenCalled(); + expect(newInternalLogger.trace).toHaveBeenCalledTimes(1); + expect(newInternalLogger.trace).toHaveBeenCalledWith('trace-message', undefined); + }); + + describe('global context', () => { + ['trace', 'debug', 'info', 'warn', 'error', 'fatal'].forEach((method) => { + test(`inserts global context in ${method} entries`, () => { + const adapter = new LoggerAdapter(internalLogger, { 'a.b.c': `${method}: d` }); + + // @ts-expect-error Custom ECS field + adapter[method](`new ${method} message`, { hello: 'world' }); + expect(internalLogger[method as keyof Logger]).toHaveBeenCalledTimes(1); + expect(internalLogger[method as keyof Logger]).toHaveBeenCalledWith( + `new ${method} message`, + { + hello: 'world', + a: { b: { c: `${method}: d` } }, + } + ); + + adapter.updateGlobalContext({ e: true }); + + // @ts-expect-error Custom ECS field + adapter[method](`another new ${method} message`, { hello: 'world' }); + expect(internalLogger[method as keyof Logger]).toHaveBeenCalledTimes(2); + expect(internalLogger[method as keyof Logger]).toHaveBeenCalledWith( + `another new ${method} message`, + { + hello: 'world', + e: true, + } + ); + }); + }); + + test('inserts global meta in log entries', () => { + const adapter = new LoggerAdapter(internalLogger, { 'a.b.c': 'd' }); + + adapter.log({ + message: 'message', + meta: { + // @ts-expect-error Custom ECS field + hello: 'world', + }, + }); + expect(internalLogger.log).toHaveBeenCalledTimes(1); + expect(internalLogger.log).toHaveBeenCalledWith({ + message: 'message', + meta: { + hello: 'world', + a: { b: { c: 'd' } }, + }, + }); + + adapter.updateGlobalContext({ e: true }); + + adapter.log({ + message: 'another message', + meta: { + // @ts-expect-error Custom ECS field + hello: 'world', + }, + }); + expect(internalLogger.log).toHaveBeenCalledTimes(2); + expect(internalLogger.log).toHaveBeenCalledWith({ + message: 'another message', + meta: { + hello: 'world', + e: true, + }, + }); + }); + + test('does not overwrite user-provided meta with global meta if the path already exists', () => { + const adapter = new LoggerAdapter(internalLogger, { hello: 'there' }); + + // @ts-expect-error Custom ECS field + adapter.info('message', { hello: 'world' }); + expect(internalLogger.info).toHaveBeenCalledTimes(1); + expect(internalLogger.info).toHaveBeenCalledWith('message', { + hello: 'world', + }); + }); + + test('does nothing if no global meta has been set', () => { + const adapter = new LoggerAdapter(internalLogger); + + // @ts-expect-error Custom ECS field + adapter.info('message', { hello: 'world' }); + expect(internalLogger.info).toHaveBeenCalledTimes(1); + expect(internalLogger.info).toHaveBeenCalledWith('message', { + hello: 'world', + }); + }); + + test('adds global meta even if no user-provided meta exists', () => { + const adapter = new LoggerAdapter(internalLogger, { hello: 'there' }); + + adapter.info('message'); + expect(internalLogger.info).toHaveBeenCalledTimes(1); + expect(internalLogger.info).toHaveBeenCalledWith('message', { + hello: 'there', + }); + }); + + test('does nothing if no global meta or user-provided meta has been set', () => { + const adapter = new LoggerAdapter(internalLogger); -test('forwards all method calls to new internal logger if it is updated.', () => { - const oldInternalLogger: Logger = { - debug: jest.fn(), - error: jest.fn(), - fatal: jest.fn(), - info: jest.fn(), - log: jest.fn(), - trace: jest.fn(), - warn: jest.fn(), - get: jest.fn(), - }; - - const newInternalLogger: Logger = { - debug: jest.fn(), - error: jest.fn(), - fatal: jest.fn(), - info: jest.fn(), - log: jest.fn(), - trace: jest.fn(), - warn: jest.fn(), - get: jest.fn(), - }; - - const adapter = new LoggerAdapter(oldInternalLogger); - - adapter.trace('trace-message'); - expect(oldInternalLogger.trace).toHaveBeenCalledTimes(1); - expect(oldInternalLogger.trace).toHaveBeenCalledWith('trace-message', undefined); - (oldInternalLogger.trace as jest.Mock<() => void>).mockReset(); - - adapter.updateLogger(newInternalLogger); - adapter.trace('trace-message'); - expect(oldInternalLogger.trace).not.toHaveBeenCalled(); - expect(newInternalLogger.trace).toHaveBeenCalledTimes(1); - expect(newInternalLogger.trace).toHaveBeenCalledWith('trace-message', undefined); + adapter.info('message'); + expect(internalLogger.info).toHaveBeenCalledTimes(1); + expect(internalLogger.info).toHaveBeenCalledWith('message', undefined); + }); + }); }); diff --git a/packages/core/logging/core-logging-server-internal/src/logger_adapter.ts b/packages/core/logging/core-logging-server-internal/src/logger_adapter.ts index d2a2c7f52923a..5439fe0205796 100644 --- a/packages/core/logging/core-logging-server-internal/src/logger_adapter.ts +++ b/packages/core/logging/core-logging-server-internal/src/logger_adapter.ts @@ -7,10 +7,11 @@ */ import { LogRecord, Logger, LogMeta } from '@kbn/logging'; +import { GlobalContext, mergeGlobalContext } from './global_context'; /** @internal */ export class LoggerAdapter implements Logger { - constructor(private logger: Logger) {} + constructor(private logger: Logger, private globalContext: GlobalContext = {}) {} /** * The current logger can be updated "on the fly", e.g. when the log config @@ -24,32 +25,44 @@ export class LoggerAdapter implements Logger { this.logger = logger; } + /** + * The current record of {@link GlobalContext} that can be updated on the fly. + * Any updates via this method will be applied to all subsequent log entries. + * + * This is not intended for external use, only internally in Kibana + * + * @internal + */ + public updateGlobalContext(context: GlobalContext) { + this.globalContext = context; + } + public trace(message: string, meta?: LogMeta): void { - this.logger.trace(message, meta); + this.logger.trace(message, mergeGlobalContext(this.globalContext, meta)); } public debug(message: string, meta?: LogMeta): void { - this.logger.debug(message, meta); + this.logger.debug(message, mergeGlobalContext(this.globalContext, meta)); } public info(message: string, meta?: LogMeta): void { - this.logger.info(message, meta); + this.logger.info(message, mergeGlobalContext(this.globalContext, meta)); } public warn(errorOrMessage: string | Error, meta?: LogMeta): void { - this.logger.warn(errorOrMessage, meta); + this.logger.warn(errorOrMessage, mergeGlobalContext(this.globalContext, meta)); } public error(errorOrMessage: string | Error, meta?: LogMeta): void { - this.logger.error(errorOrMessage, meta); + this.logger.error(errorOrMessage, mergeGlobalContext(this.globalContext, meta)); } public fatal(errorOrMessage: string | Error, meta?: LogMeta): void { - this.logger.fatal(errorOrMessage, meta); + this.logger.fatal(errorOrMessage, mergeGlobalContext(this.globalContext, meta)); } public log(record: LogRecord) { - this.logger.log(record); + this.logger.log({ ...record, meta: mergeGlobalContext(this.globalContext, record.meta) }); } public get(...contextParts: string[]): Logger { diff --git a/packages/core/logging/core-logging-server-internal/src/logging_service.test.ts b/packages/core/logging/core-logging-server-internal/src/logging_service.test.ts index 965337fca4a31..1e8f7bddbb86b 100644 --- a/packages/core/logging/core-logging-server-internal/src/logging_service.test.ts +++ b/packages/core/logging/core-logging-server-internal/src/logging_service.test.ts @@ -22,6 +22,7 @@ const createLoggingSystemMock = () => { get: jest.fn().mockImplementation(() => loggerMock.create()), asLoggerFactory: jest.fn().mockImplementation(() => loggerMock.create()), setContextConfig: jest.fn(), + setGlobalContext: jest.fn(), upgrade: jest.fn(), stop: jest.fn(), }; diff --git a/packages/core/logging/core-logging-server-internal/src/logging_system.test.mocks.ts b/packages/core/logging/core-logging-server-internal/src/logging_system.test.mocks.ts new file mode 100644 index 0000000000000..abda107ae2144 --- /dev/null +++ b/packages/core/logging/core-logging-server-internal/src/logging_system.test.mocks.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 { merge, getFlattenedObject } from '@kbn/std'; + +export const mockStreamWrite = jest.fn(); +jest.doMock('fs', () => ({ + ...(jest.requireActual('fs') as any), + constants: {}, + createWriteStream: jest.fn(() => ({ write: mockStreamWrite })), +})); + +export const mockGetFlattenedObject = jest.fn().mockImplementation(getFlattenedObject); +jest.doMock('@kbn/std', () => ({ + merge: jest.fn().mockImplementation(merge), + getFlattenedObject: mockGetFlattenedObject, +})); diff --git a/packages/core/logging/core-logging-server-internal/src/logging_system.test.ts b/packages/core/logging/core-logging-server-internal/src/logging_system.test.ts index ebe06326f499d..724319dbfb565 100644 --- a/packages/core/logging/core-logging-server-internal/src/logging_system.test.ts +++ b/packages/core/logging/core-logging-server-internal/src/logging_system.test.ts @@ -6,12 +6,7 @@ * Side Public License, v 1. */ -const mockStreamWrite = jest.fn(); -jest.mock('fs', () => ({ - ...(jest.requireActual('fs') as any), - constants: {}, - createWriteStream: jest.fn(() => ({ write: mockStreamWrite })), -})); +import { mockStreamWrite, mockGetFlattenedObject } from './logging_system.test.mocks'; const dynamicProps = { process: { pid: expect.any(Number) } }; @@ -34,6 +29,7 @@ afterEach(() => { jest.restoreAllMocks(); mockCreateWriteStream.mockClear(); mockStreamWrite.mockClear(); + mockGetFlattenedObject.mockClear(); }); test('uses default memory buffer logger until config is provided', () => { @@ -521,3 +517,115 @@ test('buffers log records for appenders created during config upgrade', async () await upgradePromise; expect(JSON.parse(mockConsoleLog.mock.calls[0][0]).message).toBe('message to a new context'); }); + +test('setGlobalContext() applies meta to new and existing loggers', async () => { + await system.upgrade( + config.schema.validate({ + appenders: { default: { type: 'console', layout: { type: 'json' } } }, + root: { level: 'info' }, + }) + ); + + const existingLogger = system.get('some-existing-context'); + // @ts-expect-error Custom ECS field + system.setGlobalContext({ a: { b: { c: true } } }); + const newLogger = system.get('some-new-context'); + + existingLogger.info('You know, just for your info.'); + newLogger.info('You know, just for your info.'); + // @ts-expect-error Custom ECS field + existingLogger.warn('You have been warned.', { someMeta: 'goes here' }); + // @ts-expect-error Custom ECS field + newLogger.warn('You have been warned.', { someMeta: 'goes here' }); + + expect(mockConsoleLog).toHaveBeenCalledTimes(4); + expect(JSON.parse(mockConsoleLog.mock.calls[0][0])).toMatchObject({ + log: { logger: 'some-existing-context' }, + message: 'You know, just for your info.', + a: { b: { c: true } }, + }); + expect(JSON.parse(mockConsoleLog.mock.calls[1][0])).toMatchObject({ + log: { logger: 'some-new-context' }, + message: 'You know, just for your info.', + a: { b: { c: true } }, + }); + expect(JSON.parse(mockConsoleLog.mock.calls[2][0])).toMatchObject({ + log: { logger: 'some-existing-context' }, + message: 'You have been warned.', + someMeta: 'goes here', + a: { b: { c: true } }, + }); + expect(JSON.parse(mockConsoleLog.mock.calls[3][0])).toMatchObject({ + log: { logger: 'some-new-context' }, + message: 'You have been warned.', + someMeta: 'goes here', + a: { b: { c: true } }, + }); +}); + +test('new global context always overwrites existing context', async () => { + await system.upgrade( + config.schema.validate({ + appenders: { default: { type: 'console', layout: { type: 'json' } } }, + root: { level: 'info' }, + }) + ); + + const logger = system.get('some-context'); + + // @ts-expect-error Custom ECS field + system.setGlobalContext({ a: { b: { c: true } }, d: false }); + logger.info('You know, just for your info.'); + + // @ts-expect-error Custom ECS field + system.setGlobalContext({ a: false, d: true }); + logger.info('You know, just for your info, again.'); + + expect(mockConsoleLog).toHaveBeenCalledTimes(2); + expect(JSON.parse(mockConsoleLog.mock.calls[0][0])).toMatchObject({ + log: { logger: 'some-context' }, + message: 'You know, just for your info.', + a: { b: { c: true } }, + d: false, + }); + expect(JSON.parse(mockConsoleLog.mock.calls[1][0])).toMatchObject({ + log: { logger: 'some-context' }, + message: 'You know, just for your info, again.', + a: false, + d: true, + }); +}); + +test('flattens global context objects before passing to LoggerAdapter', async () => { + await system.upgrade( + config.schema.validate({ + appenders: { default: { type: 'console', layout: { type: 'json' } } }, + root: { level: 'info' }, + }) + ); + + // @ts-expect-error Custom ECS field + system.setGlobalContext({ a: { b: { c: true } }, d: false }); + + const logger = system.get('some-context'); + + // @ts-expect-error Custom ECS field + system.setGlobalContext({ d: true, e: false }); + + logger.info('You know, just for your info.'); + + expect(mockGetFlattenedObject).toHaveBeenCalledTimes(3); + expect(mockGetFlattenedObject.mock.calls[0][0]).toEqual({ + a: { b: { c: true } }, + d: false, + }); + expect(mockGetFlattenedObject.mock.calls[1][0]).toEqual({ + a: { b: { c: true } }, + d: false, + }); + expect(mockGetFlattenedObject.mock.calls[2][0]).toEqual({ + a: { b: { c: true } }, + d: true, + e: false, + }); +}); diff --git a/packages/core/logging/core-logging-server-internal/src/logging_system.ts b/packages/core/logging/core-logging-server-internal/src/logging_system.ts index a267651ebe55a..c1bdf38433189 100644 --- a/packages/core/logging/core-logging-server-internal/src/logging_system.ts +++ b/packages/core/logging/core-logging-server-internal/src/logging_system.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import { DisposableAppender, LogLevel, Logger, LoggerFactory } from '@kbn/logging'; +import { getFlattenedObject, merge } from '@kbn/std'; +import { DisposableAppender, LogLevel, Logger, LoggerFactory, LogMeta } from '@kbn/logging'; import type { LoggerConfigType, LoggerContextConfigInput } from '@kbn/core-logging-server'; import { Appenders } from './appenders/appenders'; import { BufferAppender } from './appenders/buffer/buffer_appender'; @@ -25,6 +26,7 @@ export interface ILoggingSystem extends LoggerFactory { asLoggerFactory(): LoggerFactory; upgrade(rawConfig?: LoggingConfigType): Promise; setContextConfig(baseContextParts: string[], rawConfig: LoggerContextConfigInput): Promise; + setGlobalContext(meta: Partial): void; stop(): Promise; } @@ -41,13 +43,20 @@ export class LoggingSystem implements ILoggingSystem { private readonly bufferAppender = new BufferAppender(); private readonly loggers: Map = new Map(); private readonly contextConfigs = new Map(); + private globalContext: Partial = {}; constructor() {} public get(...contextParts: string[]): Logger { const context = LoggingConfig.getLoggerContext(contextParts); if (!this.loggers.has(context)) { - this.loggers.set(context, new LoggerAdapter(this.createLogger(context, this.computedConfig))); + this.loggers.set( + context, + new LoggerAdapter( + this.createLogger(context, this.computedConfig), + getFlattenedObject(this.globalContext) + ) + ); } return this.loggers.get(context)!; } @@ -110,6 +119,23 @@ export class LoggingSystem implements ILoggingSystem { } } + /** + * A mechanism for specifying some "global" {@link LogMeta} that we want + * to inject into all log entries. + * + * @remarks + * The provided context will be merged with the meta of each individual log + * entry. In the case of conflicting keys, the global context will always be + * overridden by the log entry. + */ + public setGlobalContext(meta: Partial) { + this.globalContext = merge(this.globalContext, meta); + const flattenedContext = getFlattenedObject(this.globalContext); + for (const loggerAdapter of this.loggers.values()) { + loggerAdapter.updateGlobalContext(flattenedContext); + } + } + /** * Disposes all loggers (closes log files, clears buffers etc.). Service is not usable after * calling of this method until new config is provided via `upgrade` method. diff --git a/packages/core/logging/core-logging-server-mocks/src/logging_system.mock.ts b/packages/core/logging/core-logging-server-mocks/src/logging_system.mock.ts index b486839ddac6a..ca09498d92640 100644 --- a/packages/core/logging/core-logging-server-mocks/src/logging_system.mock.ts +++ b/packages/core/logging/core-logging-server-mocks/src/logging_system.mock.ts @@ -23,6 +23,7 @@ const createLoggingSystemMock = () => { get: jest.fn(), asLoggerFactory: jest.fn(), setContextConfig: jest.fn(), + setGlobalContext: jest.fn(), upgrade: jest.fn(), stop: jest.fn(), }; diff --git a/packages/core/node/core-node-server-internal/BUILD.bazel b/packages/core/node/core-node-server-internal/BUILD.bazel index dfbd25fdaeb73..5acec90dbd637 100644 --- a/packages/core/node/core-node-server-internal/BUILD.bazel +++ b/packages/core/node/core-node-server-internal/BUILD.bazel @@ -39,6 +39,7 @@ TYPES_DEPS = [ "//packages/kbn-config-schema:npm_module_types", "//packages/kbn-logging:npm_module_types", "//packages/core/base/core-base-server-internal:npm_module_types", + "//packages/core/logging/core-logging-server-internal:npm_module_types", "//packages/core/node/core-node-server:npm_module_types", ] diff --git a/packages/core/node/core-node-server-internal/src/node_service.test.ts b/packages/core/node/core-node-server-internal/src/node_service.test.ts index 309535905445f..a707e8ec1aed8 100644 --- a/packages/core/node/core-node-server-internal/src/node_service.test.ts +++ b/packages/core/node/core-node-server-internal/src/node_service.test.ts @@ -47,7 +47,7 @@ describe('NodeService', () => { coreContext = mockCoreContext.create({ logger, configService }); service = new NodeService(coreContext); - const { roles } = await service.preboot(); + const { roles } = await service.preboot({ loggingSystem: logger }); expect(roles.backgroundTasks).toBe(true); expect(roles.ui).toBe(true); @@ -58,7 +58,7 @@ describe('NodeService', () => { coreContext = mockCoreContext.create({ logger, configService }); service = new NodeService(coreContext); - const { roles } = await service.preboot(); + const { roles } = await service.preboot({ loggingSystem: logger }); expect(roles.backgroundTasks).toBe(true); expect(roles.ui).toBe(false); @@ -69,7 +69,7 @@ describe('NodeService', () => { coreContext = mockCoreContext.create({ logger, configService }); service = new NodeService(coreContext); - const { roles } = await service.preboot(); + const { roles } = await service.preboot({ loggingSystem: logger }); expect(roles.backgroundTasks).toBe(false); expect(roles.ui).toBe(true); @@ -80,7 +80,7 @@ describe('NodeService', () => { coreContext = mockCoreContext.create({ logger, configService }); service = new NodeService(coreContext); - const { roles } = await service.preboot(); + const { roles } = await service.preboot({ loggingSystem: logger }); expect(roles.backgroundTasks).toBe(true); expect(roles.ui).toBe(true); @@ -94,7 +94,7 @@ describe('NodeService', () => { coreContext = mockCoreContext.create({ logger, configService }); service = new NodeService(coreContext); - await service.preboot(); + await service.preboot({ loggingSystem: logger }); expect(logger.get).toHaveBeenCalledTimes(1); expect(logger.get).toHaveBeenCalledWith('node'); @@ -103,5 +103,18 @@ describe('NodeService', () => { `"Kibana process configured with roles: [background_tasks, ui]"` ); }); + + it('sets the node roles in the global context', async () => { + configService = getMockedConfigService({ roles: ['*'] }); + coreContext = mockCoreContext.create({ logger, configService }); + + service = new NodeService(coreContext); + await service.preboot({ loggingSystem: logger }); + + expect(logger.setGlobalContext).toHaveBeenCalledTimes(1); + expect(logger.setGlobalContext).toHaveBeenCalledWith({ + service: { node: { roles: ['background_tasks', 'ui'] } }, + }); + }); }); }); diff --git a/packages/core/node/core-node-server-internal/src/node_service.ts b/packages/core/node/core-node-server-internal/src/node_service.ts index 10006744cf956..cd73c7f85e6f5 100644 --- a/packages/core/node/core-node-server-internal/src/node_service.ts +++ b/packages/core/node/core-node-server-internal/src/node_service.ts @@ -10,6 +10,7 @@ import { firstValueFrom } from 'rxjs'; import { camelCase } from 'lodash'; import type { IConfigService } from '@kbn/config'; import type { CoreContext } from '@kbn/core-base-server-internal'; +import type { ILoggingSystem } from '@kbn/core-logging-server-internal'; import type { NodeRoles } from '@kbn/core-node-server'; import type { Logger } from '@kbn/logging'; import { @@ -32,6 +33,10 @@ export interface InternalNodeServicePreboot { roles: NodeRoles; } +interface PrebootDeps { + loggingSystem: ILoggingSystem; +} + /** @internal */ export class NodeService { private readonly configService: IConfigService; @@ -42,18 +47,15 @@ export class NodeService { this.log = core.logger.get('node'); } - public async preboot(): Promise { - const nodeRoles = await this.getNodeRoles(); - this.log.info(`Kibana process configured with roles: [${nodeRoles.join(', ')}]`, { - service: { - // @ts-expect-error Field not available in ECS until 8.4 - node: { roles: nodeRoles }, - }, - }); + public async preboot({ loggingSystem }: PrebootDeps): Promise { + const roles = await this.getNodeRoles(); + // @ts-expect-error Custom ECS field + loggingSystem.setGlobalContext({ service: { node: { roles } } }); + this.log.info(`Kibana process configured with roles: [${roles.join(', ')}]`); return { roles: NODE_ACCEPTED_ROLES.reduce((acc, curr) => { - return { ...acc, [camelCase(curr)]: nodeRoles.includes(curr) }; + return { ...acc, [camelCase(curr)]: roles.includes(curr) }; }, {} as NodeRoles), }; } diff --git a/packages/core/test-helpers/core-test-helpers-http-setup-browser/BUILD.bazel b/packages/core/test-helpers/core-test-helpers-http-setup-browser/BUILD.bazel new file mode 100644 index 0000000000000..b802747956bda --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-http-setup-browser/BUILD.bazel @@ -0,0 +1,113 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-test-helpers-http-setup-browser" +PKG_REQUIRE_NAME = "@kbn/core-test-helpers-http-setup-browser" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "//packages/core/execution-context/core-execution-context-browser-mocks", + "//packages/core/fatal-errors/core-fatal-errors-browser-mocks", + "//packages/core/injected-metadata/core-injected-metadata-browser-mocks", + "//packages/core/http/core-http-browser-internal" +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "//packages/core/execution-context/core-execution-context-browser-mocks:npm_module_types", + "//packages/core/fatal-errors/core-fatal-errors-browser-mocks:npm_module_types", + "//packages/core/injected-metadata/core-injected-metadata-browser-mocks:npm_module_types", + "//packages/core/http/core-http-browser-internal:npm_module_types" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/test-helpers/core-test-helpers-http-setup-browser/README.md b/packages/core/test-helpers/core-test-helpers-http-setup-browser/README.md new file mode 100644 index 0000000000000..f4e1825d67d05 --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-http-setup-browser/README.md @@ -0,0 +1,3 @@ +# @kbn/core-test-helpers-http-setup-browser + +This package contains Core's browser-side test helpers. diff --git a/packages/core/test-helpers/core-test-helpers-http-setup-browser/jest.config.js b/packages/core/test-helpers/core-test-helpers-http-setup-browser/jest.config.js new file mode 100644 index 0000000000000..06aa6045ec68b --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-http-setup-browser/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/test-helpers/core-test-helpers-http-setup-browser'], +}; diff --git a/packages/core/test-helpers/core-test-helpers-http-setup-browser/package.json b/packages/core/test-helpers/core-test-helpers-http-setup-browser/package.json new file mode 100644 index 0000000000000..b6c321f96c8fc --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-http-setup-browser/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-test-helpers-http-setup-browser", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/test_helpers/http_test_setup.ts b/packages/core/test-helpers/core-test-helpers-http-setup-browser/src/http_test_setup.ts similarity index 100% rename from src/core/test_helpers/http_test_setup.ts rename to packages/core/test-helpers/core-test-helpers-http-setup-browser/src/http_test_setup.ts diff --git a/packages/core/test-helpers/core-test-helpers-http-setup-browser/src/index.ts b/packages/core/test-helpers/core-test-helpers-http-setup-browser/src/index.ts new file mode 100644 index 0000000000000..db5c37cc1ecac --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-http-setup-browser/src/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { SetupTap } from './http_test_setup'; +export { setup } from './http_test_setup'; diff --git a/packages/core/test-helpers/core-test-helpers-http-setup-browser/tsconfig.json b/packages/core/test-helpers/core-test-helpers-http-setup-browser/tsconfig.json new file mode 100644 index 0000000000000..39d3c7097814a --- /dev/null +++ b/packages/core/test-helpers/core-test-helpers-http-setup-browser/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/BUILD.bazel b/packages/core/ui-settings/core-ui-settings-browser-internal/BUILD.bazel new file mode 100644 index 0000000000000..79c90204e03c2 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/BUILD.bazel @@ -0,0 +1,113 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-ui-settings-browser-internal" +PKG_REQUIRE_NAME = "@kbn/core-ui-settings-browser-internal" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "@npm//rxjs", + "@npm//lodash", + "//packages/core/test-helpers/core-test-helpers-http-setup-browser" +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//rxjs", + "@npm//lodash", + "//packages/core/test-helpers/core-test-helpers-http-setup-browser:npm_module_types", + "//packages/core/http/core-http-browser:npm_module_types", + "//packages/core/ui-settings/core-ui-settings-browser:npm_module_types" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/README.md b/packages/core/ui-settings/core-ui-settings-browser-internal/README.md new file mode 100644 index 0000000000000..0ca0464803902 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/README.md @@ -0,0 +1,3 @@ +# @kbn/core-ui-settings-browser-internal + +This package contains the internal types and implementation for Core's browser-side uiSettings service. diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/jest.config.js b/packages/core/ui-settings/core-ui-settings-browser-internal/jest.config.js new file mode 100644 index 0000000000000..286747d11869e --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/ui-settings/core-ui-settings-browser-internal'], +}; diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/package.json b/packages/core/ui-settings/core-ui-settings-browser-internal/package.json new file mode 100644 index 0000000000000..a333808e2fe63 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-ui-settings-browser-internal", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/public/ui_settings/__snapshots__/ui_settings_api.test.ts.snap b/packages/core/ui-settings/core-ui-settings-browser-internal/src/__snapshots__/ui_settings_api.test.ts.snap similarity index 100% rename from src/core/public/ui_settings/__snapshots__/ui_settings_api.test.ts.snap rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/__snapshots__/ui_settings_api.test.ts.snap diff --git a/src/core/public/ui_settings/__snapshots__/ui_settings_client.test.ts.snap b/packages/core/ui-settings/core-ui-settings-browser-internal/src/__snapshots__/ui_settings_client.test.ts.snap similarity index 100% rename from src/core/public/ui_settings/__snapshots__/ui_settings_client.test.ts.snap rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/__snapshots__/ui_settings_client.test.ts.snap diff --git a/src/core/public/ui_settings/index.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/index.ts similarity index 87% rename from src/core/public/ui_settings/index.ts rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/index.ts index 7c7bdae34a3c1..b57cef6053106 100644 --- a/src/core/public/ui_settings/index.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/index.ts @@ -8,4 +8,3 @@ export { UiSettingsService } from './ui_settings_service'; export type { UiSettingsClient } from './ui_settings_client'; -export type { UiSettingsState, IUiSettingsClient } from './types'; diff --git a/src/core/public/ui_settings/ui_settings_api.test.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.test.ts similarity index 98% rename from src/core/public/ui_settings/ui_settings_api.test.ts rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.test.ts index d5f0f1175b9e5..c250b78d68ce5 100644 --- a/src/core/public/ui_settings/ui_settings_api.test.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.test.ts @@ -11,7 +11,7 @@ import fetchMock from 'fetch-mock/es5/client'; import * as Rx from 'rxjs'; import { takeUntil, toArray } from 'rxjs/operators'; -import { setup as httpSetup } from '../../test_helpers/http_test_setup'; +import { setup as httpSetup } from '@kbn/core-test-helpers-http-setup-browser'; import { UiSettingsApi } from './ui_settings_api'; function setup() { diff --git a/src/core/public/ui_settings/ui_settings_api.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.ts similarity index 98% rename from src/core/public/ui_settings/ui_settings_api.ts rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.ts index 0428de810cca9..2686307357723 100644 --- a/src/core/public/ui_settings/ui_settings_api.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_api.ts @@ -9,7 +9,7 @@ import { BehaviorSubject } from 'rxjs'; import type { HttpSetup } from '@kbn/core-http-browser'; -import type { UiSettingsState } from './types'; +import type { UiSettingsState } from '@kbn/core-ui-settings-browser'; export interface UiSettingsApiResponse { settings: UiSettingsState; diff --git a/src/core/public/ui_settings/ui_settings_client.test.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.test.ts similarity index 100% rename from src/core/public/ui_settings/ui_settings_client.test.ts rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.test.ts diff --git a/src/core/public/ui_settings/ui_settings_client.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts similarity index 96% rename from src/core/public/ui_settings/ui_settings_client.ts rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts index 979f6be5ebe2c..d5b6b7f1513b2 100644 --- a/src/core/public/ui_settings/ui_settings_client.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_client.ts @@ -10,8 +10,8 @@ import { cloneDeep, defaultsDeep } from 'lodash'; import { Observable, Subject, concat, defer, of } from 'rxjs'; import { filter, map } from 'rxjs/operators'; -import { UserProvidedValues, PublicUiSettingsParams } from '../../server/types'; -import { IUiSettingsClient, UiSettingsState } from './types'; +import { UserProvidedValues, PublicUiSettingsParams } from '@kbn/core-ui-settings-common'; +import { IUiSettingsClient, UiSettingsState } from '@kbn/core-ui-settings-browser'; import { UiSettingsApi } from './ui_settings_api'; diff --git a/src/core/public/ui_settings/ui_settings_service.test.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.test.ts similarity index 100% rename from src/core/public/ui_settings/ui_settings_service.test.ts rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.test.ts diff --git a/src/core/public/ui_settings/ui_settings_service.ts b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.ts similarity index 96% rename from src/core/public/ui_settings/ui_settings_service.ts rename to packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.ts index 5117ac3247af8..3ff66d8216967 100644 --- a/src/core/public/ui_settings/ui_settings_service.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/src/ui_settings_service.ts @@ -11,9 +11,9 @@ import { Subject } from 'rxjs'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; import type { HttpSetup } from '@kbn/core-http-browser'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { UiSettingsApi } from './ui_settings_api'; import { UiSettingsClient } from './ui_settings_client'; -import type { IUiSettingsClient } from './types'; export interface UiSettingsServiceDeps { http: HttpSetup; diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/tsconfig.json b/packages/core/ui-settings/core-ui-settings-browser-internal/tsconfig.json new file mode 100644 index 0000000000000..39d3c7097814a --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/BUILD.bazel b/packages/core/ui-settings/core-ui-settings-browser-mocks/BUILD.bazel new file mode 100644 index 0000000000000..c9c564ccc620a --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/BUILD.bazel @@ -0,0 +1,111 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-ui-settings-browser-mocks" +PKG_REQUIRE_NAME = "@kbn/core-ui-settings-browser-mocks" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "@npm//rxjs", + "//packages/core/ui-settings/core-ui-settings-browser-internal" +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//rxjs", + "//packages/kbn-utility-types:npm_module_types", + "//packages/core/ui-settings/core-ui-settings-browser-internal:npm_module_types", + "//packages/core/ui-settings/core-ui-settings-browser:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/README.md b/packages/core/ui-settings/core-ui-settings-browser-mocks/README.md new file mode 100644 index 0000000000000..15e17139c444f --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/README.md @@ -0,0 +1,3 @@ +# @kbn/core-ui-settings-browser-mocks + +This package contains the mocks for the browser-side uiSettings service. diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/jest.config.js b/packages/core/ui-settings/core-ui-settings-browser-mocks/jest.config.js new file mode 100644 index 0000000000000..a585eb84171ea --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/ui-settings/core-ui-settings-browser-mocks'], +}; diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/package.json b/packages/core/ui-settings/core-ui-settings-browser-mocks/package.json new file mode 100644 index 0000000000000..7d88d26720d3f --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-ui-settings-browser-mocks", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/src/index.ts b/packages/core/ui-settings/core-ui-settings-browser-mocks/src/index.ts new file mode 100644 index 0000000000000..1eaa0bff3a4c7 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/src/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { uiSettingsServiceMock } from './ui_settings_service.mock'; diff --git a/src/core/public/ui_settings/ui_settings_service.mock.ts b/packages/core/ui-settings/core-ui-settings-browser-mocks/src/ui_settings_service.mock.ts similarity index 91% rename from src/core/public/ui_settings/ui_settings_service.mock.ts rename to packages/core/ui-settings/core-ui-settings-browser-mocks/src/ui_settings_service.mock.ts index d0633c4fca1fc..834a86d03e049 100644 --- a/src/core/public/ui_settings/ui_settings_service.mock.ts +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/src/ui_settings_service.mock.ts @@ -8,8 +8,8 @@ import * as Rx from 'rxjs'; import type { PublicMethodsOf } from '@kbn/utility-types'; -import { UiSettingsService } from '.'; -import { IUiSettingsClient } from './types'; +import type { UiSettingsService } from '@kbn/core-ui-settings-browser-internal'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; const createSetupContractMock = () => { const setupContract: jest.Mocked = { diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/tsconfig.json b/packages/core/ui-settings/core-ui-settings-browser-mocks/tsconfig.json new file mode 100644 index 0000000000000..39d3c7097814a --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/ui-settings/core-ui-settings-browser/BUILD.bazel b/packages/core/ui-settings/core-ui-settings-browser/BUILD.bazel new file mode 100644 index 0000000000000..fb495d492646f --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser/BUILD.bazel @@ -0,0 +1,108 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-ui-settings-browser" +PKG_REQUIRE_NAME = "@kbn/core-ui-settings-browser" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "@npm//rxjs", +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//rxjs", + "//packages/core/ui-settings/core-ui-settings-common:npm_module_types" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/ui-settings/core-ui-settings-browser/README.md b/packages/core/ui-settings/core-ui-settings-browser/README.md new file mode 100644 index 0000000000000..7bc7eb409096b --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser/README.md @@ -0,0 +1,3 @@ +# @kbn/core-ui-settings-browser + +This package contains the public types for the browser-side ui-settings service. diff --git a/packages/core/ui-settings/core-ui-settings-browser/jest.config.js b/packages/core/ui-settings/core-ui-settings-browser/jest.config.js new file mode 100644 index 0000000000000..7ab068830f85d --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/ui-settings/core-ui-settings-browser'], +}; diff --git a/packages/core/ui-settings/core-ui-settings-browser/package.json b/packages/core/ui-settings/core-ui-settings-browser/package.json new file mode 100644 index 0000000000000..e40aeeac64196 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-ui-settings-browser", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/core/ui-settings/core-ui-settings-browser/src/index.ts b/packages/core/ui-settings/core-ui-settings-browser/src/index.ts new file mode 100644 index 0000000000000..99150ded40035 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser/src/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 type { UiSettingsState, IUiSettingsClient } from './types'; diff --git a/src/core/public/ui_settings/types.ts b/packages/core/ui-settings/core-ui-settings-browser/src/types.ts similarity index 96% rename from src/core/public/ui_settings/types.ts rename to packages/core/ui-settings/core-ui-settings-browser/src/types.ts index 243ac82ed14ab..4d23814c2b35d 100644 --- a/src/core/public/ui_settings/types.ts +++ b/packages/core/ui-settings/core-ui-settings-browser/src/types.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { Observable } from 'rxjs'; -import { PublicUiSettingsParams, UserProvidedValues } from '../../server/types'; +import type { Observable } from 'rxjs'; +import type { PublicUiSettingsParams, UserProvidedValues } from '@kbn/core-ui-settings-common'; /** @public */ export interface UiSettingsState { diff --git a/packages/core/ui-settings/core-ui-settings-browser/tsconfig.json b/packages/core/ui-settings/core-ui-settings-browser/tsconfig.json new file mode 100644 index 0000000000000..4c665fe2ba49a --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-browser/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node", + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/core/ui-settings/core-ui-settings-common/BUILD.bazel b/packages/core/ui-settings/core-ui-settings-common/BUILD.bazel new file mode 100644 index 0000000000000..92ffc8188cae5 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-common/BUILD.bazel @@ -0,0 +1,107 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-ui-settings-common" +PKG_REQUIRE_NAME = "@kbn/core-ui-settings-common" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + "src/**/*.tsx", + ], + exclude = [ + "**/*.test.*", + "**/*.stories.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "//packages/kbn-config-schema:npm_module_types", + "//packages/kbn-analytics:npm_module_types" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/ui-settings/core-ui-settings-common/README.md b/packages/core/ui-settings/core-ui-settings-common/README.md new file mode 100644 index 0000000000000..aa9cf61a0bc88 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-common/README.md @@ -0,0 +1,3 @@ +# @kbn/core-ui-settings-common + +This package contains the common types for Core's uiSettings service. diff --git a/packages/core/ui-settings/core-ui-settings-common/jest.config.js b/packages/core/ui-settings/core-ui-settings-common/jest.config.js new file mode 100644 index 0000000000000..1d7330c330d26 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-common/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/ui-settings/core-ui-settings-common'], +}; diff --git a/packages/core/ui-settings/core-ui-settings-common/package.json b/packages/core/ui-settings/core-ui-settings-common/package.json new file mode 100644 index 0000000000000..1476582f96d07 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-common/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/core-ui-settings-common", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/core/ui-settings/core-ui-settings-common/src/index.ts b/packages/core/ui-settings/core-ui-settings-common/src/index.ts new file mode 100644 index 0000000000000..da84668311cd2 --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-common/src/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 type { + UiSettingsType, + DeprecationSettings, + UiSettingsParams, + PublicUiSettingsParams, + UserProvidedValues, +} from './ui_settings'; diff --git a/src/core/types/ui_settings.ts b/packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts similarity index 96% rename from src/core/types/ui_settings.ts rename to packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts index 469f43327e498..ea1e5f92a7491 100644 --- a/src/core/types/ui_settings.ts +++ b/packages/core/ui-settings/core-ui-settings-common/src/ui_settings.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { Type } from '@kbn/config-schema'; -import { UiCounterMetricType } from '@kbn/analytics'; +import type { Type } from '@kbn/config-schema'; +import type { UiCounterMetricType } from '@kbn/analytics'; /** * UI element type to represent the settings. diff --git a/packages/core/ui-settings/core-ui-settings-common/tsconfig.json b/packages/core/ui-settings/core-ui-settings-common/tsconfig.json new file mode 100644 index 0000000000000..39d3c7097814a --- /dev/null +++ b/packages/core/ui-settings/core-ui-settings-common/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index ee2fb5143e92b..67bfabcbd0984 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -396,7 +396,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { classificationAucRoc: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-dfa-classification.html#ml-dfanalytics-class-aucroc`, setUpgradeMode: `${ELASTICSEARCH_DOCS}ml-set-upgrade-mode.html`, trainedModels: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-trained-models.html`, - startTrainedModelsDeploymentQueryParams: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/start-trained-model-deployment.html#start-trained-model-deployment-query-params`, + startTrainedModelsDeployment: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/ml-nlp-deploy-models.html#ml-nlp-deploy-model`, }, transforms: { guide: `${ELASTICSEARCH_DOCS}transforms.html`, diff --git a/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts b/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts index 4518b3631a2a0..ed5a7ff8b8135 100644 --- a/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts +++ b/packages/kbn-telemetry-tools/src/cli/run_telemetry_check.ts @@ -48,64 +48,70 @@ export function runTelemetryCheck() { ); } - const list = new Listr([ - { - title: 'Checking .telemetryrc.json files', - task: () => new Listr(parseConfigsTask(), { exitOnError: true }), - }, - { - title: 'Extracting Collectors', - task: (context) => new Listr(extractCollectorsTask(context, path), { exitOnError: true }), - }, - { - enabled: () => typeof path !== 'undefined', - title: 'Checking collectors in --path are not excluded', - task: ({ roots }: TaskContext) => { - const totalCollections = roots.reduce((acc, root) => { - return acc + (root.parsedCollections?.length || 0); - }, 0); - const collectorsInPath = Array.isArray(path) ? path.length : 1; + const list = new Listr( + [ + { + title: 'Checking .telemetryrc.json files', + task: () => new Listr(parseConfigsTask(), { exitOnError: true }), + }, + { + title: 'Extracting Collectors', + task: (context) => + new Listr(extractCollectorsTask(context, path), { exitOnError: true }), + }, + { + enabled: () => typeof path !== 'undefined', + title: 'Checking collectors in --path are not excluded', + task: ({ roots }: TaskContext) => { + const totalCollections = roots.reduce((acc, root) => { + return acc + (root.parsedCollections?.length || 0); + }, 0); + const collectorsInPath = Array.isArray(path) ? path.length : 1; - if (totalCollections !== collectorsInPath) { - throw new Error( - 'Collector specified in `path` is excluded; Check the telemetryrc.json files.' + if (totalCollections !== collectorsInPath) { + throw new Error( + 'Collector specified in `path` is excluded; Check the telemetryrc.json files.' + ); + } + }, + }, + { + title: 'Checking Compatible collector.schema with collector.fetch type', + task: (context) => new Listr(checkCompatibleTypesTask(context), { exitOnError: true }), + }, + { + enabled: (_) => fix || !ignoreStoredJson, + title: 'Checking Matching collector.schema against stored json files', + task: (context) => + new Listr(checkMatchingSchemasTask(context, !fix), { exitOnError: true }), + }, + { + enabled: (_) => fix, + skip: ({ roots }: TaskContext) => { + const noDiffs = roots.every( + ({ esMappingDiffs }) => !esMappingDiffs || !esMappingDiffs.length ); - } + return noDiffs && 'No changes needed.'; + }, + title: 'Generating new telemetry mappings', + task: (context) => new Listr(generateSchemasTask(context), { exitOnError: true }), }, - }, - { - title: 'Checking Compatible collector.schema with collector.fetch type', - task: (context) => new Listr(checkCompatibleTypesTask(context), { exitOnError: true }), - }, - { - enabled: (_) => fix || !ignoreStoredJson, - title: 'Checking Matching collector.schema against stored json files', - task: (context) => - new Listr(checkMatchingSchemasTask(context, !fix), { exitOnError: true }), - }, - { - enabled: (_) => fix, - skip: ({ roots }: TaskContext) => { - const noDiffs = roots.every( - ({ esMappingDiffs }) => !esMappingDiffs || !esMappingDiffs.length - ); - return noDiffs && 'No changes needed.'; + { + enabled: (_) => fix, + skip: ({ roots }: TaskContext) => { + const noDiffs = roots.every( + ({ esMappingDiffs }) => !esMappingDiffs || !esMappingDiffs.length + ); + return noDiffs && 'No changes needed.'; + }, + title: 'Updating telemetry mapping files', + task: (context) => new Listr(writeToFileTask(context), { exitOnError: true }), }, - title: 'Generating new telemetry mappings', - task: (context) => new Listr(generateSchemasTask(context), { exitOnError: true }), - }, + ], { - enabled: (_) => fix, - skip: ({ roots }: TaskContext) => { - const noDiffs = roots.every( - ({ esMappingDiffs }) => !esMappingDiffs || !esMappingDiffs.length - ); - return noDiffs && 'No changes needed.'; - }, - title: 'Updating telemetry mapping files', - task: (context) => new Listr(writeToFileTask(context), { exitOnError: true }), - }, - ]); + renderer: process.env.CI ? 'verbose' : 'default', + } + ); try { const context = createTaskContext(); diff --git a/packages/kbn-telemetry-tools/src/cli/run_telemetry_extract.ts b/packages/kbn-telemetry-tools/src/cli/run_telemetry_extract.ts index c998470ff0a9c..22790ab6a0578 100644 --- a/packages/kbn-telemetry-tools/src/cli/run_telemetry_extract.ts +++ b/packages/kbn-telemetry-tools/src/cli/run_telemetry_extract.ts @@ -21,24 +21,29 @@ import { export function runTelemetryExtract() { run( async ({ flags: {}, log }) => { - const list = new Listr([ + const list = new Listr( + [ + { + title: 'Parsing .telemetryrc.json files', + task: () => new Listr(parseConfigsTask(), { exitOnError: true }), + }, + { + title: 'Extracting Telemetry Collectors', + task: (context) => new Listr(extractCollectorsTask(context), { exitOnError: true }), + }, + { + title: 'Generating Schema files', + task: (context) => new Listr(generateSchemasTask(context), { exitOnError: true }), + }, + { + title: 'Writing to file', + task: (context) => new Listr(writeToFileTask(context), { exitOnError: true }), + }, + ], { - title: 'Parsing .telemetryrc.json files', - task: () => new Listr(parseConfigsTask(), { exitOnError: true }), - }, - { - title: 'Extracting Telemetry Collectors', - task: (context) => new Listr(extractCollectorsTask(context), { exitOnError: true }), - }, - { - title: 'Generating Schema files', - task: (context) => new Listr(generateSchemasTask(context), { exitOnError: true }), - }, - { - title: 'Writing to file', - task: (context) => new Listr(writeToFileTask(context), { exitOnError: true }), - }, - ]); + renderer: process.env.CI ? 'verbose' : 'default', + } + ); try { const context = createTaskContext(); diff --git a/packages/kbn-test/BUILD.bazel b/packages/kbn-test/BUILD.bazel index e2824076e80b9..b854379eb536b 100644 --- a/packages/kbn-test/BUILD.bazel +++ b/packages/kbn-test/BUILD.bazel @@ -76,6 +76,7 @@ RUNTIME_DEPS = [ "@npm//rxjs", "@npm//semver", "@npm//strip-ansi", + "@npm//supertest", "@npm//xmlbuilder", "@npm//xml2js", ] @@ -123,6 +124,7 @@ TYPES_DEPS = [ "@npm//@types/react-redux", "@npm//@types/react-router-dom", "@npm//@types/semver", + "@npm//@types/supertest", "@npm//@types/uuid", "@npm//@types/xml2js", ] diff --git a/packages/kbn-test/src/es/test_es_cluster.ts b/packages/kbn-test/src/es/test_es_cluster.ts index 1eb48ca58d950..8c650ec9b6051 100644 --- a/packages/kbn-test/src/es/test_es_cluster.ts +++ b/packages/kbn-test/src/es/test_es_cluster.ts @@ -19,11 +19,11 @@ import type { ChildProcess } from 'child_process'; import { Cluster } from '@kbn/es'; import { Client, HttpConnection } from '@elastic/elasticsearch'; import type { ToolingLog } from '@kbn/tooling-log'; +import { REPO_ROOT } from '@kbn/utils'; + import { CI_PARALLEL_PROCESS_PREFIX } from '../ci_parallel_process_prefix'; import { esTestConfig } from './es_test_config'; -import { KIBANA_ROOT } from '..'; - interface TestEsClusterNodesOptions { name: string; /** @@ -168,7 +168,7 @@ export function createTestEsCluster< password = 'changeme', license = 'basic', log, - basePath = Path.resolve(KIBANA_ROOT, '.es'), + basePath = Path.resolve(REPO_ROOT, '.es'), esFrom = esTestConfig.getBuildFrom(), dataArchive, nodes = [{ name: 'node-01' }], @@ -196,7 +196,7 @@ export function createTestEsCluster< const config = { version: esTestConfig.getVersion(), installPath: Path.resolve(basePath, clusterName), - sourcePath: Path.resolve(KIBANA_ROOT, '../elasticsearch'), + sourcePath: Path.resolve(REPO_ROOT, '../elasticsearch'), password, license, basePath, @@ -321,7 +321,7 @@ export function createTestEsCluster< } const uuid = Uuid.v4(); - const debugPath = Path.resolve(KIBANA_ROOT, `data/es_debug_${uuid}.tar.gz`); + const debugPath = Path.resolve(REPO_ROOT, `data/es_debug_${uuid}.tar.gz`); log.error(`[es] debug files found, archiving install to ${debugPath}`); const archiver = createArchiver('tar', { gzip: true }); const promise = pipeline(archiver, Fs.createWriteStream(debugPath)); diff --git a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts index 9de6500a45323..4e549e960dc26 100644 --- a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts +++ b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts @@ -24,6 +24,7 @@ import { Config, SuiteTracker, EsVersion, + DedicatedTaskRunner, } from './lib'; import { createEsClientForFtrConfig } from '../es'; @@ -242,6 +243,7 @@ export class FunctionalTestRunner { config: () => config, dockerServers: () => dockerServers, esVersion: () => this.esVersion, + dedicatedTaskRunner: () => new DedicatedTaskRunner(config, this.log), }); return await handler(config, lifecycle, coreProviders); diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index bf652bf8c8444..6f5757a73ea0a 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -216,6 +216,7 @@ export const schema = Joi.object() sourceArgs: Joi.array(), serverArgs: Joi.array(), installDir: Joi.string(), + useDedicatedTaskRunner: Joi.boolean().default(false), /** Options for how FTR should execute and interact with Kibana */ runOptions: Joi.object() .keys({ diff --git a/packages/kbn-test/src/functional_test_runner/lib/dedicated_task_runner.ts b/packages/kbn-test/src/functional_test_runner/lib/dedicated_task_runner.ts new file mode 100644 index 0000000000000..20b5e0387c719 --- /dev/null +++ b/packages/kbn-test/src/functional_test_runner/lib/dedicated_task_runner.ts @@ -0,0 +1,138 @@ +/* + * Copyright 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 Url from 'url'; + +import { ToolingLog } from '@kbn/tooling-log'; +import Supertest from 'supertest'; + +import { KbnClient } from '../../kbn_client'; +import { Config } from './config'; +import { getKibanaCliArg } from '../../functional_tests/lib/kibana_cli_args'; + +export class DedicatedTaskRunner { + static getPort(uiPort: number) { + return uiPort + 13; + } + + static getUuid(mainUuid: string) { + if (mainUuid.length !== 36) { + throw new Error(`invalid mainUuid: ${mainUuid}`); + } + + return `00000000-${mainUuid.slice(9)}`; + } + + /** + * True when the FTR config indicates that Kibana has a dedicated task runner process, otherwise false. If this + * property is false then all other methods on this class will throw when they are called, so if you're not + * certain where your code will be run make sure to check `dedicatedTaskRunner.enabled` before calling + * other methods. + */ + public readonly enabled: boolean; + + private readonly enabledProps?: { + readonly port: number; + readonly url: string; + readonly client: KbnClient; + readonly uuid?: string; + readonly supertest?: Supertest.SuperTest; + }; + + constructor(config: Config, log: ToolingLog) { + if (!config.get('kbnTestServer.useDedicatedTaskRunner')) { + this.enabled = false; + return; + } + + this.enabled = true; + + const port = DedicatedTaskRunner.getPort(config.get('servers.kibana.port')); + const url = Url.format({ + ...config.get('servers.kibana'), + port, + }); + const client = new KbnClient({ + log, + url, + certificateAuthorities: config.get('servers.kibana.certificateAuthorities'), + uiSettingDefaults: config.get('uiSettings.defaults'), + }); + + const mainUuid = getKibanaCliArg(config.get('kbnTestServer.serverArgs'), 'server.uuid'); + const uuid = typeof mainUuid === 'string' ? DedicatedTaskRunner.getUuid(mainUuid) : undefined; + + this.enabledProps = { port, url, client, uuid }; + } + + private getEnabledProps() { + if (!this.enabledProps) { + throw new Error( + `DedicatedTaskRunner is not enabled, check the "enabled" property before calling getters assuming it is enabled.` + ); + } + + return this.enabledProps; + } + + /** + * The port number that the dedicated task runner is running on + */ + getPort() { + return this.getEnabledProps().port; + } + + /** + * The full URL for the dedicated task runner process + */ + getUrl() { + return this.getEnabledProps().url; + } + + /** + * Returns true if the `--server.uuid` setting was passed to the Kibana server, allowing the UUID to + * be deterministic and ensuring that `dedicatedTaskRunner.getUuid()` won't throw. + */ + hasUuid() { + return !!this.getEnabledProps().uuid; + } + + /** + * If `--server.uuid` is passed to Kibana in the FTR config file then the dedicated task runner will + * use a UUID derived from that and it will be synchronously available to users via this function. + * Otherwise this function will through. + */ + getUuid() { + const uuid = this.getEnabledProps().uuid; + if (!uuid) { + throw new Error( + 'Pass `--server.uuid` the the Kibana server in your FTR config in order to make the UUID of the dedicated task runner deterministic.' + ); + } + + return uuid; + } + + /** + * @returns a `KbnClient` instance that is configured to talk directly to the dedicated task runner. Not really sure how useful this is. + */ + getClient() { + return this.getEnabledProps().client; + } + + /** + * @returns a Supertest instance that will send requests to the dedicated task runner. + * + * @example + * const supertest = dedicatedTaskRunner.getSupertest(); + * const response = await supertest.get('/status'); + */ + getSupertest() { + return Supertest(this.getUrl()); + } +} diff --git a/packages/kbn-test/src/functional_test_runner/lib/index.ts b/packages/kbn-test/src/functional_test_runner/lib/index.ts index b269e34178851..983a185dee682 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/index.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/index.ts @@ -14,6 +14,7 @@ export * from './providers'; export { runTests, setupMocha } from './mocha'; export * from './docker_servers'; export { SuiteTracker } from './suite_tracker'; +export { DedicatedTaskRunner } from './dedicated_task_runner'; export type { Provider } from './providers'; export * from './es_version'; diff --git a/packages/kbn-test/src/functional_test_runner/public_types.ts b/packages/kbn-test/src/functional_test_runner/public_types.ts index 67adceaf22323..3faa19de73ce1 100644 --- a/packages/kbn-test/src/functional_test_runner/public_types.ts +++ b/packages/kbn-test/src/functional_test_runner/public_types.ts @@ -8,7 +8,13 @@ import type { ToolingLog } from '@kbn/tooling-log'; -import type { Config, Lifecycle, DockerServersService, EsVersion } from './lib'; +import type { + Config, + Lifecycle, + DockerServersService, + EsVersion, + DedicatedTaskRunner, +} from './lib'; import type { Test, Suite } from './fake_mocha_types'; export { Lifecycle, Config }; @@ -56,7 +62,15 @@ export interface GenericFtrProviderContext< * Determine if a service is avaliable * @param serviceName */ - hasService(serviceName: 'config' | 'log' | 'lifecycle' | 'dockerServers' | 'esVersion'): true; + hasService( + serviceName: + | 'config' + | 'log' + | 'lifecycle' + | 'dockerServers' + | 'esVersion' + | 'dedicatedTaskRunner' + ): true; hasService(serviceName: K): serviceName is K; hasService(serviceName: string): serviceName is Extract; @@ -70,6 +84,7 @@ export interface GenericFtrProviderContext< getService(serviceName: 'lifecycle'): Lifecycle; getService(serviceName: 'dockerServers'): DockerServersService; getService(serviceName: 'esVersion'): EsVersion; + getService(serviceName: 'dedicatedTaskRunner'): DedicatedTaskRunner; getService(serviceName: T): ServiceMap[T]; /** diff --git a/packages/kbn-test/src/functional_tests/lib/index.ts b/packages/kbn-test/src/functional_tests/lib/index.ts index 2726192328bda..8844a2ee59a19 100644 --- a/packages/kbn-test/src/functional_tests/lib/index.ts +++ b/packages/kbn-test/src/functional_tests/lib/index.ts @@ -10,5 +10,4 @@ export { runKibanaServer } from './run_kibana_server'; export { runElasticsearch } from './run_elasticsearch'; export type { CreateFtrOptions, CreateFtrParams } from './run_ftr'; export { runFtr, hasTests, assertNoneExcluded } from './run_ftr'; -export { KIBANA_ROOT, KIBANA_FTR_SCRIPT } from './paths'; export { runCli } from './run_cli'; diff --git a/packages/kbn-test/src/functional_tests/lib/paths.ts b/packages/kbn-test/src/functional_tests/lib/paths.ts deleted file mode 100644 index 76357d447dc2a..0000000000000 --- a/packages/kbn-test/src/functional_tests/lib/paths.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 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 { REPO_ROOT } from '@kbn/utils'; -import { resolve, relative } from 'path'; - -// resolve() treats relative paths as relative to process.cwd(), -// so to return a relative path we use relative() -function resolveRelative(path: string) { - return relative(process.cwd(), resolve(path)); -} - -export const KIBANA_EXEC = 'node'; -export const KIBANA_SCRIPT_PATH = resolveRelative('scripts/kibana'); -export const KIBANA_ROOT = REPO_ROOT; -export const KIBANA_FTR_SCRIPT = resolve(KIBANA_ROOT, 'scripts/functional_test_runner'); diff --git a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts index 2ee9de4053fef..5dcee56e765e0 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts +++ b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts @@ -9,7 +9,7 @@ import { resolve } from 'path'; import type { ToolingLog } from '@kbn/tooling-log'; import getPort from 'get-port'; -import { KIBANA_ROOT } from './paths'; +import { REPO_ROOT } from '@kbn/utils'; import type { Config } from '../../functional_test_runner'; import { createTestEsCluster } from '../../es'; @@ -106,7 +106,7 @@ async function startEsNode( port: config.port, ssl: config.ssl, log, - basePath: resolve(KIBANA_ROOT, '.es'), + basePath: resolve(REPO_ROOT, '.es'), nodes: [ { name, diff --git a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts index 7b6d6d5cd1a3e..54e01a6b7916b 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts +++ b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts @@ -7,12 +7,15 @@ */ import Path from 'path'; +import Os from 'os'; +import Uuid from 'uuid'; import type { ProcRunner } from '@kbn/dev-proc-runner'; +import { REPO_ROOT } from '@kbn/utils'; -import { KIBANA_ROOT, KIBANA_EXEC, KIBANA_SCRIPT_PATH } from './paths'; import type { Config } from '../../functional_test_runner'; -import { parseRawFlags } from './kibana_cli_args'; +import { DedicatedTaskRunner } from '../../functional_test_runner/lib'; +import { parseRawFlags, getArgValue } from './kibana_cli_args'; function extendNodeOptions(installDir?: string) { if (!installDir) { @@ -44,13 +47,35 @@ export async function runKibanaServer({ }) { const runOptions = config.get('kbnTestServer.runOptions'); const installDir = runOptions.alwaysUseSource ? undefined : options.installDir; - const extraArgs = options.extraKbnOpts ?? []; + const devMode = !installDir; + const useTaskRunner = config.get('kbnTestServer.useDedicatedTaskRunner'); + + const procRunnerOpts = { + cwd: installDir || REPO_ROOT, + cmd: installDir + ? process.platform.startsWith('win') + ? Path.resolve(installDir, 'bin/kibana.bat') + : Path.resolve(installDir, 'bin/kibana') + : process.execPath, + env: { + FORCE_COLOR: 1, + ...process.env, + ...config.get('kbnTestServer.env'), + ...extendNodeOptions(installDir), + }, + wait: runOptions.wait, + onEarlyExit, + }; + + const prefixArgs = devMode + ? [Path.relative(procRunnerOpts.cwd, Path.resolve(REPO_ROOT, 'scripts/kibana'))] + : []; const buildArgs: string[] = config.get('kbnTestServer.buildArgs') || []; const sourceArgs: string[] = config.get('kbnTestServer.sourceArgs') || []; const serverArgs: string[] = config.get('kbnTestServer.serverArgs') || []; - const args = parseRawFlags([ + const kbnFlags = parseRawFlags([ // When installDir is passed, we run from a built version of Kibana which uses different command line // arguments. If installDir is not passed, we run from source code. ...(installDir @@ -58,31 +83,51 @@ export async function runKibanaServer({ : [...sourceArgs, ...serverArgs]), // We also allow passing in extra Kibana server options, tack those on here so they always take precedence - ...extraArgs, + ...(options.extraKbnOpts ?? []), ]); - // main process - await procs.run('kibana', { - cmd: getKibanaCmd(installDir), - args: installDir ? args : [KIBANA_SCRIPT_PATH, ...args], - env: { - FORCE_COLOR: 1, - ...process.env, - ...config.get('kbnTestServer.env'), - ...extendNodeOptions(installDir), - }, - cwd: installDir || KIBANA_ROOT, - wait: runOptions.wait, - onEarlyExit, - }); -} + const promises = [ + // main process + procs.run(useTaskRunner ? 'kbn-ui' : 'kibana', { + ...procRunnerOpts, + args: [ + ...prefixArgs, + ...parseRawFlags([ + ...kbnFlags, + ...(!useTaskRunner + ? [] + : [ + '--node.roles=["ui"]', + `--path.data=${Path.resolve(Os.tmpdir(), `ftr-ui-${Uuid.v4()}`)}`, + ]), + ]), + ], + }), + ]; + + if (useTaskRunner) { + const mainUuid = getArgValue(kbnFlags, 'server.uuid'); -function getKibanaCmd(installDir?: string) { - if (installDir) { - return process.platform.startsWith('win') - ? Path.resolve(installDir, 'bin/kibana.bat') - : Path.resolve(installDir, 'bin/kibana'); + // dedicated task runner + promises.push( + procs.run('kbn-tasks', { + ...procRunnerOpts, + args: [ + ...prefixArgs, + ...parseRawFlags([ + ...kbnFlags, + `--server.port=${DedicatedTaskRunner.getPort(config.get('servers.kibana.port'))}`, + '--node.roles=["background_tasks"]', + `--path.data=${Path.resolve(Os.tmpdir(), `ftr-task-runner-${Uuid.v4()}`)}`, + ...(typeof mainUuid === 'string' && mainUuid + ? [`--server.uuid=${DedicatedTaskRunner.getUuid(mainUuid)}`] + : []), + ...(devMode ? ['--no-optimizer'] : []), + ]), + ], + }) + ); } - return KIBANA_EXEC; + await Promise.all(promises); } diff --git a/packages/kbn-test/src/functional_tests/tasks.ts b/packages/kbn-test/src/functional_tests/tasks.ts index 76cc4dde1f36b..9b5fb5424f3fe 100644 --- a/packages/kbn-test/src/functional_tests/tasks.ts +++ b/packages/kbn-test/src/functional_tests/tasks.ts @@ -6,9 +6,10 @@ * Side Public License, v 1. */ -import { relative } from 'path'; -import * as Rx from 'rxjs'; +import Path from 'path'; import { setTimeout } from 'timers/promises'; + +import * as Rx from 'rxjs'; import { startWith, switchMap, take } from 'rxjs/operators'; import { withProcRunner } from '@kbn/dev-proc-runner'; import { ToolingLog } from '@kbn/tooling-log'; @@ -16,17 +17,17 @@ import { getTimeReporter } from '@kbn/ci-stats-reporter'; import { REPO_ROOT } from '@kbn/utils'; import dedent from 'dedent'; +import { readConfigFile, EsVersion } from '../functional_test_runner/lib'; import { runElasticsearch, runKibanaServer, runFtr, assertNoneExcluded, hasTests, - KIBANA_FTR_SCRIPT, CreateFtrOptions, } from './lib'; -import { readConfigFile, EsVersion } from '../functional_test_runner/lib'; +const FTR_SCRIPT_PATH = Path.resolve(REPO_ROOT, 'scripts/functional_test_runner'); const makeSuccessMessage = (options: StartServerOptions) => { const installDirFlag = options.installDir ? ` --kibana-install-dir=${options.installDir}` : ''; @@ -34,7 +35,7 @@ const makeSuccessMessage = (options: StartServerOptions) => { const pathsMessage = options.useDefaultConfig ? '' : configPaths - .map((path) => relative(process.cwd(), path)) + .map((path) => Path.relative(process.cwd(), path)) .map((path) => ` --config ${path}`) .join(''); @@ -44,7 +45,7 @@ const makeSuccessMessage = (options: StartServerOptions) => { Elasticsearch and Kibana are ready for functional testing. Start the functional tests in another terminal session by running this command from this directory: - node ${relative(process.cwd(), KIBANA_FTR_SCRIPT)}${installDirFlag}${pathsMessage} + node ${Path.relative(process.cwd(), FTR_SCRIPT_PATH)}${installDirFlag}${pathsMessage} ` + '\n\n' ); @@ -96,7 +97,7 @@ export async function runTests(options: RunTestsParams) { await log.indent(0, async () => { if (options.configs.length > 1) { const progress = `${i + 1}/${options.configs.length}`; - log.write(`--- [${progress}] Running ${relative(REPO_ROOT, configPath)}`); + log.write(`--- [${progress}] Running ${Path.relative(REPO_ROOT, configPath)}`); } if (!(await hasTests({ configPath, options: { ...options, log } }))) { diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index 7770232011d21..6d67bbecc2093 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -24,9 +24,6 @@ export { runTestsCli, processRunTestsCliOptions, startServersCli, processStartSe // @internal export { runTests, startServers } from './functional_tests/tasks'; -// @internal -export { KIBANA_ROOT } from './functional_tests/lib/paths'; - export { getKibanaCliArg, getKibanaCliLoggers } from './functional_tests/lib/kibana_cli_args'; export type { diff --git a/src/core/public/chrome/chrome_service.test.ts b/src/core/public/chrome/chrome_service.test.ts index f5d276ef25172..737b561bed8e3 100644 --- a/src/core/public/chrome/chrome_service.test.ts +++ b/src/core/public/chrome/chrome_service.test.ts @@ -16,7 +16,7 @@ import { httpServiceMock } from '@kbn/core-http-browser-mocks'; import { App, PublicAppInfo } from '../application'; import { applicationServiceMock } from '../application/application_service.mock'; import { notificationServiceMock } from '../notifications/notifications_service.mock'; -import { uiSettingsServiceMock } from '../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { ChromeService } from './chrome_service'; import { getAppInfo } from '../application/utils'; diff --git a/src/core/public/core_app/core_app.ts b/src/core/public/core_app/core_app.ts index 82ae595f86477..d834ece6e76cf 100644 --- a/src/core/public/core_app/core_app.ts +++ b/src/core/public/core_app/core_app.ts @@ -11,6 +11,7 @@ import type { CoreContext } from '@kbn/core-base-browser-internal'; import type { InternalInjectedMetadataSetup } from '@kbn/core-injected-metadata-browser-internal'; import type { DocLinksStart } from '@kbn/core-doc-links-browser'; import type { HttpSetup, HttpStart } from '@kbn/core-http-browser'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { type InternalApplicationSetup, type InternalApplicationStart, @@ -18,7 +19,6 @@ import { type AppMountParameters, } from '../application'; import type { NotificationsSetup, NotificationsStart } from '../notifications'; -import type { IUiSettingsClient } from '../ui_settings'; import { renderApp as renderErrorApp, setupPublicBaseUrlConfigWarning, diff --git a/src/core/public/core_app/errors/url_overflow.test.ts b/src/core/public/core_app/errors/url_overflow.test.ts index 0e166e5d5e7ee..e68b80931d2ec 100644 --- a/src/core/public/core_app/errors/url_overflow.test.ts +++ b/src/core/public/core_app/errors/url_overflow.test.ts @@ -11,9 +11,9 @@ import type { IBasePath } from '@kbn/core-http-browser'; import { BasePath } from '@kbn/core-http-browser-internal'; import { notificationServiceMock } from '../../notifications/notifications_service.mock'; -import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import type { IToasts } from '../../notifications'; -import type { IUiSettingsClient } from '../../ui_settings'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { setupUrlOverflowDetection, URL_MAX_LENGTH, URL_WARNING_LENGTH } from './url_overflow'; diff --git a/src/core/public/core_app/errors/url_overflow.tsx b/src/core/public/core_app/errors/url_overflow.tsx index f2a525a9c2e68..4925cf18c0f77 100644 --- a/src/core/public/core_app/errors/url_overflow.tsx +++ b/src/core/public/core_app/errors/url_overflow.tsx @@ -13,9 +13,9 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { IBasePath } from '@kbn/core-http-browser'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { mountReactNode } from '../../utils'; import { IToasts } from '../../notifications'; -import { IUiSettingsClient } from '../../ui_settings'; const IE_REGEX = /(; ?MSIE |Edge\/\d|Trident\/[\d+\.]+;.*rv:*11\.\d+)/; export const IS_IE = IE_REGEX.test(window.navigator.userAgent); diff --git a/src/core/public/core_system.test.mocks.ts b/src/core/public/core_system.test.mocks.ts index 0d46af80b34eb..baf4c28401c06 100644 --- a/src/core/public/core_system.test.mocks.ts +++ b/src/core/public/core_system.test.mocks.ts @@ -18,7 +18,7 @@ import { i18nServiceMock } from '@kbn/core-i18n-browser-mocks'; import { notificationServiceMock } from './notifications/notifications_service.mock'; import { overlayServiceMock } from './overlays/overlay_service.mock'; import { pluginsServiceMock } from './plugins/plugins_service.mock'; -import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { renderingServiceMock } from './rendering/rendering_service.mock'; import { integrationsServiceMock } from './integrations/integrations_service.mock'; import { coreAppMock } from './core_app/core_app.mock'; @@ -76,7 +76,7 @@ export const MockUiSettingsService = uiSettingsServiceMock.create(); export const UiSettingsServiceConstructor = jest .fn() .mockImplementation(() => MockUiSettingsService); -jest.doMock('./ui_settings', () => ({ +jest.doMock('@kbn/core-ui-settings-browser-internal', () => ({ UiSettingsService: UiSettingsServiceConstructor, })); diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 636c44dd3a6e0..710d7b90c4c30 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -23,17 +23,17 @@ import { ExecutionContextService } from '@kbn/core-execution-context-browser-int import type { FatalErrorsSetup } from '@kbn/core-fatal-errors-browser'; import { FatalErrorsService } from '@kbn/core-fatal-errors-browser-internal'; import { HttpService } from '@kbn/core-http-browser-internal'; +import { UiSettingsService } from '@kbn/core-ui-settings-browser-internal'; +import { DeprecationsService } from '@kbn/core-deprecations-browser-internal'; import { CoreSetup, CoreStart } from '.'; import { ChromeService } from './chrome'; import { NotificationsService } from './notifications'; import { OverlayService } from './overlays'; import { PluginsService } from './plugins'; -import { UiSettingsService } from './ui_settings'; import { ApplicationService } from './application'; import { RenderingService } from './rendering'; import { SavedObjectsService } from './saved_objects'; import { IntegrationsService } from './integrations'; -import { DeprecationsService } from './deprecations'; import { CoreApp } from './core_app'; import type { InternalApplicationSetup, InternalApplicationStart } from './application/types'; import { fetchOptionalMemoryInfo } from './fetch_optional_memory_info'; diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 5e224c38a2dc4..ccde84105ea89 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -42,6 +42,8 @@ import type { FatalErrorsStart, FatalErrorInfo, } from '@kbn/core-fatal-errors-browser'; +import type { UiSettingsState, IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import type { DeprecationsServiceStart } from '@kbn/core-deprecations-browser'; import type { ChromeBadge, ChromeBreadcrumb, @@ -72,17 +74,20 @@ import type { PluginInitializerContext, PluginOpaqueId, } from './plugins'; -import type { UiSettingsState, IUiSettingsClient } from './ui_settings'; import type { ApplicationSetup, Capabilities, ApplicationStart } from './application'; import type { SavedObjectsStart } from './saved_objects'; -import type { DeprecationsServiceStart } from './deprecations'; export type { PackageInfo, EnvironmentMode } from '@kbn/config'; -export type { DomainDeprecationDetails } from '../server/types'; +export type { DomainDeprecationDetails } from '@kbn/core-deprecations-common'; export type { CoreContext } from '@kbn/core-base-browser-internal'; export type { CoreSystem } from './core_system'; export { DEFAULT_APP_CATEGORIES, APP_WRAPPER_CLASS } from '../utils'; -export type { AppCategory, UiSettingsParams, UserProvidedValues, UiSettingsType } from '../types'; +export type { AppCategory } from '../types'; +export type { + UiSettingsParams, + UserProvidedValues, + UiSettingsType, +} from '@kbn/core-ui-settings-common'; export type { AnalyticsServiceSetup, AnalyticsServiceStart } from '@kbn/core-analytics-browser'; export type { @@ -210,7 +215,10 @@ export type { export type { ThemeServiceSetup, ThemeServiceStart, CoreTheme } from '@kbn/core-theme-browser'; -export type { DeprecationsServiceStart, ResolveDeprecationResponse } from './deprecations'; +export type { + DeprecationsServiceStart, + ResolveDeprecationResponse, +} from '@kbn/core-deprecations-browser'; export type { MountPoint, UnmountCallback, PublicUiSettingsParams } from './types'; diff --git a/src/core/public/integrations/integrations_service.test.ts b/src/core/public/integrations/integrations_service.test.ts index 9543012833feb..a98e5bf1d7bc2 100644 --- a/src/core/public/integrations/integrations_service.test.ts +++ b/src/core/public/integrations/integrations_service.test.ts @@ -9,7 +9,7 @@ import { styleServiceMock, momentServiceMock } from './integrations_service.test.mocks'; import { IntegrationsService } from './integrations_service'; -import { uiSettingsServiceMock } from '../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; describe('IntegrationsService', () => { test('it wires up styles and moment', async () => { diff --git a/src/core/public/integrations/integrations_service.ts b/src/core/public/integrations/integrations_service.ts index e03546998ba7e..ca01e1b86ce7e 100644 --- a/src/core/public/integrations/integrations_service.ts +++ b/src/core/public/integrations/integrations_service.ts @@ -7,7 +7,7 @@ */ import type { CoreService } from '@kbn/core-base-browser-internal'; -import { IUiSettingsClient } from '../ui_settings'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { MomentService } from './moment'; import { StylesService } from './styles'; diff --git a/src/core/public/integrations/moment/moment_service.test.ts b/src/core/public/integrations/moment/moment_service.test.ts index 4e7c345e7e05d..d3c4d44f100e8 100644 --- a/src/core/public/integrations/moment/moment_service.test.ts +++ b/src/core/public/integrations/moment/moment_service.test.ts @@ -8,7 +8,7 @@ import { momentMock } from './moment_service.test.mocks'; import { MomentService } from './moment_service'; -import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { BehaviorSubject } from 'rxjs'; describe('MomentService', () => { diff --git a/src/core/public/integrations/moment/moment_service.ts b/src/core/public/integrations/moment/moment_service.ts index 0f58c8d7fb19f..633223864f202 100644 --- a/src/core/public/integrations/moment/moment_service.ts +++ b/src/core/public/integrations/moment/moment_service.ts @@ -11,7 +11,7 @@ import { merge, Subscription } from 'rxjs'; import { tap } from 'rxjs/operators'; import type { CoreService } from '@kbn/core-base-browser-internal'; -import { IUiSettingsClient } from '../../ui_settings'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; interface StartDeps { uiSettings: IUiSettingsClient; diff --git a/src/core/public/integrations/styles/styles_service.test.ts b/src/core/public/integrations/styles/styles_service.test.ts index 5fae4b976c59e..20625dcbc3b94 100644 --- a/src/core/public/integrations/styles/styles_service.test.ts +++ b/src/core/public/integrations/styles/styles_service.test.ts @@ -11,7 +11,7 @@ import { BehaviorSubject } from 'rxjs'; jest.mock('!!raw-loader!./disable_animations.css', () => 'MOCK DISABLE ANIMATIONS CSS'); import { StylesService } from './styles_service'; -import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; describe('StylesService', () => { const flushPromises = () => new Promise((resolve) => setTimeout(resolve, 100)); diff --git a/src/core/public/integrations/styles/styles_service.ts b/src/core/public/integrations/styles/styles_service.ts index 3e8f02739a8d0..9bbed46ff12f5 100644 --- a/src/core/public/integrations/styles/styles_service.ts +++ b/src/core/public/integrations/styles/styles_service.ts @@ -9,7 +9,7 @@ import { Subscription } from 'rxjs'; import type { CoreService } from '@kbn/core-base-browser-internal'; -import { IUiSettingsClient } from '../../ui_settings'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; // @ts-expect-error import disableAnimationsCss from '!!raw-loader!./disable_animations.css'; diff --git a/src/core/public/mocks.ts b/src/core/public/mocks.ts index b3070d46feee8..73e4a5a80fbde 100644 --- a/src/core/public/mocks.ts +++ b/src/core/public/mocks.ts @@ -17,6 +17,8 @@ import { executionContextServiceMock } from '@kbn/core-execution-context-browser import { i18nServiceMock } from '@kbn/core-i18n-browser-mocks'; import { fatalErrorsServiceMock } from '@kbn/core-fatal-errors-browser-mocks'; import { httpServiceMock } from '@kbn/core-http-browser-mocks'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; +import { deprecationsServiceMock } from '@kbn/core-deprecations-browser-mocks'; import type { PluginInitializerContext, AppMountParameters } from '.'; // Import values from their individual modules instead. import { ScopedHistory } from './application'; @@ -24,9 +26,7 @@ import { applicationServiceMock } from './application/application_service.mock'; import { chromeServiceMock } from './chrome/chrome_service.mock'; import { notificationServiceMock } from './notifications/notifications_service.mock'; import { overlayServiceMock } from './overlays/overlay_service.mock'; -import { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; import { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; -import { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; export { injectedMetadataServiceMock } from '@kbn/core-injected-metadata-browser-mocks'; export { docLinksServiceMock } from '@kbn/core-doc-links-browser-mocks'; @@ -39,11 +39,11 @@ export { httpServiceMock } from '@kbn/core-http-browser-mocks'; export { i18nServiceMock } from '@kbn/core-i18n-browser-mocks'; export { notificationServiceMock } from './notifications/notifications_service.mock'; export { overlayServiceMock } from './overlays/overlay_service.mock'; -export { uiSettingsServiceMock } from './ui_settings/ui_settings_service.mock'; +export { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; export { savedObjectsServiceMock } from './saved_objects/saved_objects_service.mock'; export { scopedHistoryMock } from './application/scoped_history.mock'; export { applicationServiceMock } from './application/application_service.mock'; -export { deprecationsServiceMock } from './deprecations/deprecations_service.mock'; +export { deprecationsServiceMock } from '@kbn/core-deprecations-browser-mocks'; function createCoreSetupMock({ basePath = '', diff --git a/src/core/public/notifications/notifications_service.ts b/src/core/public/notifications/notifications_service.ts index 859e21de5ffed..6a5a5f81f1a40 100644 --- a/src/core/public/notifications/notifications_service.ts +++ b/src/core/public/notifications/notifications_service.ts @@ -11,8 +11,8 @@ import { i18n } from '@kbn/i18n'; import { Subscription } from 'rxjs'; import type { ThemeServiceStart } from '@kbn/core-theme-browser'; import type { I18nStart } from '@kbn/core-i18n-browser'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { ToastsService, ToastsSetup, ToastsStart } from './toasts'; -import { IUiSettingsClient } from '../ui_settings'; import { OverlayStart } from '../overlays'; export interface SetupDeps { diff --git a/src/core/public/notifications/toasts/toasts_api.test.ts b/src/core/public/notifications/toasts/toasts_api.test.ts index d6b67bdb63f7a..ec07f32d2f1c9 100644 --- a/src/core/public/notifications/toasts/toasts_api.test.ts +++ b/src/core/public/notifications/toasts/toasts_api.test.ts @@ -10,7 +10,7 @@ import { firstValueFrom } from 'rxjs'; import { ToastsApi } from './toasts_api'; -import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { i18nServiceMock } from '@kbn/core-i18n-browser-mocks'; async function getCurrentToasts(toasts: ToastsApi) { diff --git a/src/core/public/notifications/toasts/toasts_api.tsx b/src/core/public/notifications/toasts/toasts_api.tsx index ecf32d442931c..f78927c7f7579 100644 --- a/src/core/public/notifications/toasts/toasts_api.tsx +++ b/src/core/public/notifications/toasts/toasts_api.tsx @@ -12,10 +12,10 @@ import * as Rx from 'rxjs'; import { omitBy, isUndefined } from 'lodash'; import type { I18nStart } from '@kbn/core-i18n-browser'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { ErrorToast } from './error_toast'; import { MountPoint } from '../../types'; import { mountReactNode } from '../../utils'; -import { IUiSettingsClient } from '../../ui_settings'; import { OverlayStart } from '../../overlays'; /** diff --git a/src/core/public/notifications/toasts/toasts_service.test.tsx b/src/core/public/notifications/toasts/toasts_service.test.tsx index d2694d076e8c0..a6854f679d086 100644 --- a/src/core/public/notifications/toasts/toasts_service.test.tsx +++ b/src/core/public/notifications/toasts/toasts_service.test.tsx @@ -12,7 +12,7 @@ import { ToastsService } from './toasts_service'; import { ToastsApi } from './toasts_api'; import { overlayServiceMock } from '../../overlays/overlay_service.mock'; import { themeServiceMock } from '@kbn/core-theme-browser-mocks'; -import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; const mockI18n: any = { Context: function I18nContext() { diff --git a/src/core/public/notifications/toasts/toasts_service.tsx b/src/core/public/notifications/toasts/toasts_service.tsx index 63edd56085797..692e6ec9dd504 100644 --- a/src/core/public/notifications/toasts/toasts_service.tsx +++ b/src/core/public/notifications/toasts/toasts_service.tsx @@ -12,7 +12,7 @@ import { render, unmountComponentAtNode } from 'react-dom'; import type { ThemeServiceStart } from '@kbn/core-theme-browser'; import type { I18nStart } from '@kbn/core-i18n-browser'; import { CoreContextProvider } from '@kbn/core-theme-browser-internal'; -import { IUiSettingsClient } from '../../ui_settings'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { GlobalToastList } from './global_toast_list'; import { ToastsApi, IToasts } from './toasts_api'; import { OverlayStart } from '../../overlays'; diff --git a/src/core/public/overlays/banners/banners_service.test.ts b/src/core/public/overlays/banners/banners_service.test.ts index d3093879f8715..69f30d99b9826 100644 --- a/src/core/public/overlays/banners/banners_service.test.ts +++ b/src/core/public/overlays/banners/banners_service.test.ts @@ -9,7 +9,7 @@ import { OverlayBannersService, OverlayBannersStart } from './banners_service'; import { take } from 'rxjs/operators'; import { i18nServiceMock } from '@kbn/core-i18n-browser-mocks'; -import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; describe('OverlayBannersService', () => { let service: OverlayBannersStart; diff --git a/src/core/public/overlays/banners/banners_service.tsx b/src/core/public/overlays/banners/banners_service.tsx index a5436d21ef45e..11bc995c059f8 100644 --- a/src/core/public/overlays/banners/banners_service.tsx +++ b/src/core/public/overlays/banners/banners_service.tsx @@ -11,9 +11,9 @@ import { BehaviorSubject, Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import type { I18nStart } from '@kbn/core-i18n-browser'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { PriorityMap } from './priority_map'; import { BannersList } from './banners_list'; -import { IUiSettingsClient } from '../../ui_settings'; import { MountPoint } from '../../types'; import { UserBannerService } from './user_banner_service'; diff --git a/src/core/public/overlays/banners/user_banner_service.test.ts b/src/core/public/overlays/banners/user_banner_service.test.ts index 52d6d00171261..e0a46cbb7fd6a 100644 --- a/src/core/public/overlays/banners/user_banner_service.test.ts +++ b/src/core/public/overlays/banners/user_banner_service.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { uiSettingsServiceMock } from '../../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { UserBannerService } from './user_banner_service'; import { overlayBannersServiceMock } from './banners_service.mock'; import { i18nServiceMock } from '@kbn/core-i18n-browser-mocks'; diff --git a/src/core/public/overlays/banners/user_banner_service.tsx b/src/core/public/overlays/banners/user_banner_service.tsx index 175d43ea8ba59..7d3c9eab9b17f 100644 --- a/src/core/public/overlays/banners/user_banner_service.tsx +++ b/src/core/public/overlays/banners/user_banner_service.tsx @@ -15,7 +15,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiCallOut, EuiButton, EuiLoadingSpinner } from '@elastic/eui'; import type { I18nStart } from '@kbn/core-i18n-browser'; -import { IUiSettingsClient } from '../../ui_settings'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { OverlayBannersStart } from './banners_service'; interface StartDeps { diff --git a/src/core/public/overlays/overlay_service.ts b/src/core/public/overlays/overlay_service.ts index 35e839b0e175b..07a8cbea29a37 100644 --- a/src/core/public/overlays/overlay_service.ts +++ b/src/core/public/overlays/overlay_service.ts @@ -8,7 +8,7 @@ import type { ThemeServiceStart } from '@kbn/core-theme-browser'; import type { I18nStart } from '@kbn/core-i18n-browser'; -import { IUiSettingsClient } from '../ui_settings'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { OverlayBannersStart, OverlayBannersService } from './banners'; import { FlyoutService, OverlayFlyoutStart } from './flyout'; import { ModalService, OverlayModalStart } from './modal'; diff --git a/src/core/public/plugins/plugins_service.test.ts b/src/core/public/plugins/plugins_service.test.ts index d956b0e8599a3..dbc3fd253a1c1 100644 --- a/src/core/public/plugins/plugins_service.test.ts +++ b/src/core/public/plugins/plugins_service.test.ts @@ -34,11 +34,11 @@ import { applicationServiceMock } from '../application/application_service.mock' import { overlayServiceMock } from '../overlays/overlay_service.mock'; import { chromeServiceMock } from '../chrome/chrome_service.mock'; import { fatalErrorsServiceMock } from '@kbn/core-fatal-errors-browser-mocks'; -import { uiSettingsServiceMock } from '../ui_settings/ui_settings_service.mock'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { httpServiceMock } from '@kbn/core-http-browser-mocks'; import type { CoreSetup, CoreStart, PluginInitializerContext } from '..'; import { savedObjectsServiceMock } from '../saved_objects/saved_objects_service.mock'; -import { deprecationsServiceMock } from '../deprecations/deprecations_service.mock'; +import { deprecationsServiceMock } from '@kbn/core-deprecations-browser-mocks'; export let mockPluginInitializers: Map; diff --git a/src/core/public/types.ts b/src/core/public/types.ts index 5b594373e3523..8df8b2c10f179 100644 --- a/src/core/public/types.ts +++ b/src/core/public/types.ts @@ -11,7 +11,7 @@ export type { PublicUiSettingsParams, UserProvidedValues, UiSettingsType, -} from '../types'; +} from '@kbn/core-ui-settings-common'; /** * A function that should mount DOM content inside the provided container element diff --git a/src/core/server/deprecations/deprecations_factory.test.ts b/src/core/server/deprecations/deprecations_factory.test.ts index b05a3ea3ce4dc..3ae83a1886e5c 100644 --- a/src/core/server/deprecations/deprecations_factory.test.ts +++ b/src/core/server/deprecations/deprecations_factory.test.ts @@ -9,7 +9,7 @@ import type { GetDeprecationsContext } from './types'; import { DeprecationsFactory, DeprecationsFactoryConfig } from './deprecations_factory'; import { loggerMock } from '@kbn/logging-mocks'; -import { DeprecationsDetails } from './types'; +import type { DeprecationsDetails } from '@kbn/core-deprecations-common'; describe('DeprecationsFactory', () => { let logger: ReturnType; diff --git a/src/core/server/deprecations/deprecations_factory.ts b/src/core/server/deprecations/deprecations_factory.ts index d36d61fa2eab2..514817ed1c12a 100644 --- a/src/core/server/deprecations/deprecations_factory.ts +++ b/src/core/server/deprecations/deprecations_factory.ts @@ -8,12 +8,9 @@ import { i18n } from '@kbn/i18n'; import type { Logger } from '@kbn/logging'; +import type { DomainDeprecationDetails, DeprecationsDetails } from '@kbn/core-deprecations-common'; import { DeprecationsRegistry } from './deprecations_registry'; -import type { - DomainDeprecationDetails, - DeprecationsDetails, - GetDeprecationsContext, -} from './types'; +import type { GetDeprecationsContext } from './types'; export interface DeprecationsFactoryDeps { logger: Logger; diff --git a/src/core/server/deprecations/deprecations_registry.ts b/src/core/server/deprecations/deprecations_registry.ts index e979bb94712e6..6e59504d0d1d7 100644 --- a/src/core/server/deprecations/deprecations_registry.ts +++ b/src/core/server/deprecations/deprecations_registry.ts @@ -7,12 +7,8 @@ */ import { withTimeout, isPromise } from '@kbn/std'; -import type { - DeprecationsDetails, - RegisterDeprecationsConfig, - GetDeprecationsContext, -} from './types'; - +import type { DeprecationsDetails } from '@kbn/core-deprecations-common'; +import type { RegisterDeprecationsConfig, GetDeprecationsContext } from './types'; const MsInSec = 1000; export class DeprecationsRegistry { diff --git a/src/core/server/deprecations/deprecations_service.ts b/src/core/server/deprecations/deprecations_service.ts index 6d8aef2ef84e8..7b07b4c1d10de 100644 --- a/src/core/server/deprecations/deprecations_service.ts +++ b/src/core/server/deprecations/deprecations_service.ts @@ -7,13 +7,13 @@ */ import { firstValueFrom } from 'rxjs'; - import type { Logger } from '@kbn/logging'; import type { IConfigService } from '@kbn/config'; import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; +import { DomainDeprecationDetails } from '@kbn/core-deprecations-common'; import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; import { DeprecationsFactory } from './deprecations_factory'; -import { DomainDeprecationDetails, RegisterDeprecationsConfig } from './types'; +import { RegisterDeprecationsConfig } from './types'; import { registerRoutes } from './routes'; import { config as deprecationConfig, DeprecationConfigType } from './deprecation_config'; import { IScopedClusterClient } from '../elasticsearch/client'; diff --git a/src/core/server/deprecations/index.ts b/src/core/server/deprecations/index.ts index 9245179d3099a..db6fe8193867d 100644 --- a/src/core/server/deprecations/index.ts +++ b/src/core/server/deprecations/index.ts @@ -6,15 +6,7 @@ * Side Public License, v 1. */ -export type { - BaseDeprecationDetails, - DeprecationsDetails, - ConfigDeprecationDetails, - FeatureDeprecationDetails, - GetDeprecationsContext, - RegisterDeprecationsConfig, - DeprecationsGetResponse, -} from './types'; +export type { GetDeprecationsContext, RegisterDeprecationsConfig } from './types'; export type { DeprecationsServiceSetup, diff --git a/src/core/server/deprecations/routes/get.ts b/src/core/server/deprecations/routes/get.ts index a3ea08f04d706..1ae70e47c2b62 100644 --- a/src/core/server/deprecations/routes/get.ts +++ b/src/core/server/deprecations/routes/get.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { DeprecationsGetResponse } from '../types'; +import type { DeprecationsGetResponse } from '@kbn/core-deprecations-common'; import type { InternalDeprecationRouter } from '../internal_types'; export const registerGetRoute = (router: InternalDeprecationRouter) => { diff --git a/src/core/server/deprecations/types.ts b/src/core/server/deprecations/types.ts index 3990a76f7578e..16104c6f9cc57 100644 --- a/src/core/server/deprecations/types.ts +++ b/src/core/server/deprecations/types.ts @@ -7,102 +7,10 @@ */ import type { MaybePromise } from '@kbn/utility-types'; +import type { DeprecationsDetails } from '@kbn/core-deprecations-common'; import type { SavedObjectsClientContract } from '../saved_objects/types'; import type { IScopedClusterClient } from '../elasticsearch'; -/** - * Base properties shared by all types of deprecations - * - * @public - */ -export interface BaseDeprecationDetails { - /** - * The title of the deprecation. - * Check the README for writing deprecations in `src/core/server/deprecations/README.mdx` - */ - title: string; - /** - * The description message to be displayed for the deprecation. - * Check the README for writing deprecations in `src/core/server/deprecations/README.mdx` - */ - message: string; - /** - * levels: - * - warning: will not break deployment upon upgrade - * - critical: needs to be addressed before upgrade. - * - fetch_error: Deprecations service failed to grab the deprecation details for the domain. - */ - level: 'warning' | 'critical' | 'fetch_error'; - /** - * (optional) Used to identify between different deprecation types. - * Example use case: in Upgrade Assistant, we may want to allow the user to sort by - * deprecation type or show each type in a separate tab. - * - * Feel free to add new types if necessary. - * Predefined types are necessary to reduce having similar definitions with different keywords - * across kibana deprecations. - */ - deprecationType?: 'config' | 'feature'; - /** (optional) link to the documentation for more details on the deprecation. */ - documentationUrl?: string; - /** (optional) specify the fix for this deprecation requires a full kibana restart. */ - requireRestart?: boolean; - /** corrective action needed to fix this deprecation. */ - correctiveActions: { - /** - * (optional) The api to be called to automatically fix the deprecation - * Each domain should implement a POST/PUT route for their plugin to - * handle their deprecations. - */ - api?: { - /** Kibana route path. Passing a query string is allowed */ - path: string; - /** Kibana route method: 'POST' or 'PUT'. */ - method: 'POST' | 'PUT'; - /** Additional details to be passed to the route. */ - body?: { - [key: string]: any; - }; - /* Allow to omit context in the request of the body */ - omitContextFromBody?: boolean; - }; - /** - * Specify a list of manual steps users need to follow to - * fix the deprecation before upgrade. Required even if an API - * corrective action is set in case the API fails. - * Check the README for writing deprecations in `src/core/server/deprecations/README.mdx` - */ - manualSteps: string[]; - }; -} - -/** - * @public - */ -export interface ConfigDeprecationDetails extends BaseDeprecationDetails { - configPath: string; - deprecationType: 'config'; -} - -/** - * @public - */ -export interface FeatureDeprecationDetails extends BaseDeprecationDetails { - deprecationType?: 'feature' | undefined; -} - -/** - * @public - */ -export type DeprecationsDetails = ConfigDeprecationDetails | FeatureDeprecationDetails; - -/** - * @internal - */ -export type DomainDeprecationDetails = DeprecationsDetails & { - domainId: string; -}; - /** * @public */ @@ -117,10 +25,3 @@ export interface GetDeprecationsContext { esClient: IScopedClusterClient; savedObjectsClient: SavedObjectsClientContract; } - -/** - * @public - */ -export interface DeprecationsGetResponse { - deprecations: DomainDeprecationDetails[]; -} diff --git a/src/core/server/index.ts b/src/core/server/index.ts index 9dc6a88bacca5..82d98f875241e 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -405,17 +405,13 @@ export { EventLoopDelaysMonitor } from './metrics'; export type { I18nServiceSetup } from './i18n'; export type { - BaseDeprecationDetails, - DeprecationsDetails, - ConfigDeprecationDetails, - FeatureDeprecationDetails, RegisterDeprecationsConfig, GetDeprecationsContext, DeprecationsServiceSetup, DeprecationsClient, DeprecationsRequestHandlerContext, } from './deprecations'; - +export type { DeprecationsDetails } from '@kbn/core-deprecations-common'; export type { AppCategory } from '../types'; export { DEFAULT_APP_CATEGORIES, APP_WRAPPER_CLASS } from '../utils'; diff --git a/src/core/server/node/integration_tests/logging.test.ts b/src/core/server/node/integration_tests/logging.test.ts new file mode 100644 index 0000000000000..931e56beeab73 --- /dev/null +++ b/src/core/server/node/integration_tests/logging.test.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as kbnTestServer from '../../../test_helpers/kbn_server'; + +function createRootWithRoles(roles: string[]) { + return kbnTestServer.createRoot({ + node: { + roles, + }, + logging: { + appenders: { + 'test-console': { + type: 'console', + layout: { + type: 'json', + }, + }, + }, + root: { + appenders: ['test-console'], + level: 'info', + }, + }, + }); +} + +describe('node service global context', () => { + const validRoles = [['ui', 'background_tasks'], ['ui'], ['background_tasks']]; + + validRoles.forEach((roles) => { + describe(`with node.roles: ${roles}`, () => { + let root: ReturnType; + let mockConsoleLog: jest.SpyInstance; + + beforeAll(async () => { + mockConsoleLog = jest.spyOn(global.console, 'log'); + root = createRootWithRoles(roles); + + await root.preboot(); + await root.setup(); + }, 30000); + + beforeEach(() => { + mockConsoleLog.mockClear(); + }); + + afterAll(async () => { + mockConsoleLog.mockRestore(); + await root.shutdown(); + }); + + it('logs the correct roles in service.node.roles', () => { + const logger = root.logger.get('foo.bar'); + + logger.info('test info'); + + expect(mockConsoleLog).toHaveBeenCalledTimes(1); + expect(JSON.parse(mockConsoleLog.mock.calls[0][0])).toEqual( + expect.objectContaining({ service: { node: { roles } } }) + ); + }); + }); + }); +}); diff --git a/src/core/server/saved_objects/deprecations/unknown_object_types.ts b/src/core/server/saved_objects/deprecations/unknown_object_types.ts index 9e48c84860b48..d8762ebcfd1bd 100644 --- a/src/core/server/saved_objects/deprecations/unknown_object_types.ts +++ b/src/core/server/saved_objects/deprecations/unknown_object_types.ts @@ -7,7 +7,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { DeprecationsDetails } from '../../deprecations'; +import type { DeprecationsDetails } from '@kbn/core-deprecations-common'; import { IScopedClusterClient } from '../../elasticsearch'; import { getAggregatedTypesDocuments } from '../migrations/actions/check_for_unknown_docs'; import { addExcludedTypesToBoolQuery } from '../migrations/model/helpers'; diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 6f5e072aa1fa7..5f811723845c1 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -167,7 +167,7 @@ export class Server { const analyticsPreboot = this.analytics.preboot(); const environmentPreboot = await this.environment.preboot({ analytics: analyticsPreboot }); - const nodePreboot = await this.node.preboot(); + const nodePreboot = await this.node.preboot({ loggingSystem: this.loggingSystem }); // Discover any plugins before continuing. This allows other systems to utilize the plugin dependency graph. this.discoveredPlugins = await this.plugins.discover({ diff --git a/src/core/server/types.ts b/src/core/server/types.ts index 0e49ebbf851d6..1bcdd1ac09535 100644 --- a/src/core/server/types.ts +++ b/src/core/server/types.ts @@ -42,6 +42,9 @@ export type { SavedObjectReferenceWithContext, SavedObjectsCollectMultiNamespaceReferencesResponse, } from './saved_objects/service'; -export type { DomainDeprecationDetails, DeprecationsGetResponse } from './deprecations/types'; +export type { + DomainDeprecationDetails, + DeprecationsGetResponse, +} from '@kbn/core-deprecations-common'; export * from './ui_settings/types'; export type { ExternalUrlConfig } from '@kbn/core-http-server-internal'; diff --git a/src/core/server/ui_settings/types.ts b/src/core/server/ui_settings/types.ts index c442e37c4b022..a7405e8b75731 100644 --- a/src/core/server/ui_settings/types.ts +++ b/src/core/server/ui_settings/types.ts @@ -5,16 +5,20 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { + UiSettingsParams, + UserProvidedValues, + PublicUiSettingsParams, +} from '@kbn/core-ui-settings-common'; import { SavedObjectsClientContract } from '../saved_objects/types'; -import { UiSettingsParams, UserProvidedValues, PublicUiSettingsParams } from '../../types'; export type { UiSettingsParams, - PublicUiSettingsParams, DeprecationSettings, + PublicUiSettingsParams, UiSettingsType, UserProvidedValues, -} from '../../types'; +} from '@kbn/core-ui-settings-common'; /** * Server-side client that provides access to the advanced settings stored in elasticsearch. diff --git a/src/core/types/index.ts b/src/core/types/index.ts index 7b9df84770365..005e5fb611cfb 100644 --- a/src/core/types/index.ts +++ b/src/core/types/index.ts @@ -12,6 +12,12 @@ */ export * from './capabilities'; export * from './app_category'; -export * from './ui_settings'; export * from './saved_objects'; export type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; +export type { + UiSettingsType, + DeprecationSettings, + UiSettingsParams, + PublicUiSettingsParams, + UserProvidedValues, +} from '@kbn/core-ui-settings-common'; diff --git a/src/dev/precommit_hook/casing_check_config.js b/src/dev/precommit_hook/casing_check_config.js index b16dc39c4f50b..0c65b924f14b1 100644 --- a/src/dev/precommit_hook/casing_check_config.js +++ b/src/dev/precommit_hook/casing_check_config.js @@ -53,9 +53,6 @@ export const IGNORE_FILE_GLOBS = [ '**/preview-body.html', '**/preview-head.html', - // filename required by api-extractor - 'api-documenter.json', - // filename must match upstream filenames from lodash 'packages/elastic-safer-lodash-set/**/*', diff --git a/src/dev/run_i18n_check.ts b/src/dev/run_i18n_check.ts index 2aa9f65f4d3db..220eef24f3808 100644 --- a/src/dev/run_i18n_check.ts +++ b/src/dev/run_i18n_check.ts @@ -120,6 +120,7 @@ run( { concurrent: false, exitOnError: true, + renderer: process.env.CI ? 'verbose' : 'default', } ); diff --git a/src/dev/run_i18n_extract.ts b/src/dev/run_i18n_extract.ts index 6ff9eb5164ad2..2c1f39e929a36 100644 --- a/src/dev/run_i18n_extract.ts +++ b/src/dev/run_i18n_extract.ts @@ -38,32 +38,37 @@ run( } const srcPaths = Array().concat(path || ['./src', './packages', './x-pack']); - const list = new Listr([ - { - title: 'Merging .i18nrc.json files', - task: () => new Listr(mergeConfigs(includeConfig), { exitOnError: true }), - }, - { - title: 'Extracting Default Messages', - task: ({ config }) => - new Listr(extractDefaultMessages(config, srcPaths), { exitOnError: true }), - }, - { - title: 'Writing to file', - enabled: (ctx) => outputDir && ctx.messages.size, - task: async (ctx) => { - const sortedMessages = [...ctx.messages].sort(([key1], [key2]) => - key1.localeCompare(key2) - ); - await writeFileAsync( - resolve(outputDir, 'en.json'), - outputFormat === 'json5' - ? serializeToJson5(sortedMessages) - : serializeToJson(sortedMessages) - ); + const list = new Listr( + [ + { + title: 'Merging .i18nrc.json files', + task: () => new Listr(mergeConfigs(includeConfig), { exitOnError: true }), + }, + { + title: 'Extracting Default Messages', + task: ({ config }) => + new Listr(extractDefaultMessages(config, srcPaths), { exitOnError: true }), }, - }, - ]); + { + title: 'Writing to file', + enabled: (ctx) => outputDir && ctx.messages.size, + task: async (ctx) => { + const sortedMessages = [...ctx.messages].sort(([key1], [key2]) => + key1.localeCompare(key2) + ); + await writeFileAsync( + resolve(outputDir, 'en.json'), + outputFormat === 'json5' + ? serializeToJson5(sortedMessages) + : serializeToJson(sortedMessages) + ); + }, + }, + ], + { + renderer: process.env.CI ? 'verbose' : 'default', + } + ); try { const reporter = new ErrorReporter(); diff --git a/src/dev/run_i18n_integrate.ts b/src/dev/run_i18n_integrate.ts index 29696ca5f9aa5..80e2f8cb1f33b 100644 --- a/src/dev/run_i18n_integrate.ts +++ b/src/dev/run_i18n_integrate.ts @@ -69,33 +69,38 @@ run( const srcPaths = Array().concat(path || ['./src', './packages', './x-pack']); - const list = new Listr([ - { - title: 'Merging .i18nrc.json files', - task: () => new Listr(mergeConfigs(includeConfig), { exitOnError: true }), - }, - { - title: 'Extracting Default Messages', - task: ({ config }) => - new Listr(extractDefaultMessages(config, srcPaths), { exitOnError: true }), - }, - { - title: 'Integrating Locale File', - task: async ({ messages, config }) => { - await integrateLocaleFiles(messages, { - sourceFileName: source, - targetFileName: target, - dryRun, - ignoreIncompatible, - ignoreUnused, - ignoreMissing, - ignoreMalformed, - config, - log, - }); + const list = new Listr( + [ + { + title: 'Merging .i18nrc.json files', + task: () => new Listr(mergeConfigs(includeConfig), { exitOnError: true }), + }, + { + title: 'Extracting Default Messages', + task: ({ config }) => + new Listr(extractDefaultMessages(config, srcPaths), { exitOnError: true }), }, - }, - ]); + { + title: 'Integrating Locale File', + task: async ({ messages, config }) => { + await integrateLocaleFiles(messages, { + sourceFileName: source, + targetFileName: target, + dryRun, + ignoreIncompatible, + ignoreUnused, + ignoreMissing, + ignoreMalformed, + config, + log, + }); + }, + }, + ], + { + renderer: process.env.CI ? 'verbose' : 'default', + } + ); try { const reporter = new ErrorReporter(); diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index e1360d3b63e4e..e4b87a07af907 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -20,6 +20,7 @@ export const storybookAliases = { data: 'src/plugins/data/.storybook', discover: 'src/plugins/discover/.storybook', embeddable: 'src/plugins/embeddable/.storybook', + es_ui_shared: 'src/plugins/es_ui_shared/.storybook', expression_error: 'src/plugins/expression_error/.storybook', expression_image: 'src/plugins/expression_image/.storybook', expression_metric_vis: 'src/plugins/chart_expressions/expression_metric/.storybook', diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/annotation_layer.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/annotation_layer.ts index 6174b9d40e452..4635fc5924b90 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/annotation_layer.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/annotation_layer.ts @@ -24,10 +24,10 @@ export function annotationLayerFunction(): ExpressionFunctionDefinition< inputTypes: ['datatable'], help: strings.getAnnotationLayerFnHelp(), args: { - hide: { + simpleView: { types: ['boolean'], default: false, - help: strings.getAnnotationLayerHideHelp(), + help: strings.getAnnotationLayerSimpleViewHelp(), }, annotations: { types: ['manual_point_event_annotation', 'manual_range_event_annotation'], diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_data_layer_args.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_data_layer_args.ts index 330e31327873a..0c173ea0754f8 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_data_layer_args.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/common_data_layer_args.ts @@ -20,10 +20,10 @@ export const commonDataLayerArgs: Omit< CommonDataLayerFnArgs, 'accessors' | 'xAccessor' | 'splitAccessor' > = { - hide: { + simpleView: { types: ['boolean'], default: false, - help: strings.getHideHelp(), + help: strings.getSimpleView(), }, seriesType: { aliases: ['_'], diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts index 539c11854355c..2e3f9e160ebb4 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/extended_annotation_layer.ts @@ -24,10 +24,10 @@ export function extendedAnnotationLayerFunction(): ExpressionFunctionDefinition< inputTypes: ['datatable'], help: strings.getAnnotationLayerFnHelp(), args: { - hide: { + simpleView: { types: ['boolean'], default: false, - help: strings.getAnnotationLayerHideHelp(), + help: strings.getAnnotationLayerSimpleViewHelp(), }, annotations: { types: ['manual_point_event_annotation', 'manual_range_event_annotation'], diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts index ea619fa7e1c28..789b7fb9ceb63 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/xy_vis_fn.ts @@ -42,7 +42,7 @@ const createDataLayer = (args: XYArgs, table: Datatable): DataLayerConfigResult return { type: DATA_LAYER, seriesType: args.seriesType, - hide: args.hide, + simpleView: args.simpleView, columnToLabel: args.columnToLabel, xScaleType: args.xScaleType, isHistogram: args.isHistogram, @@ -72,7 +72,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { seriesType, accessors, xAccessor, - hide, + simpleView, splitAccessors, columnToLabel, xScaleType, diff --git a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx index 9d1388829de3c..75a523ab41d92 100644 --- a/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/common/i18n/index.tsx @@ -125,9 +125,9 @@ export const strings = { i18n.translate('expressionXY.dataLayer.help', { defaultMessage: `Configure a layer in the xy chart`, }), - getHideHelp: () => - i18n.translate('expressionXY.dataLayer.hide.help', { - defaultMessage: 'Show / hide axis', + getSimpleView: () => + i18n.translate('expressionXY.dataLayer.simpleView.help', { + defaultMessage: 'Show / hide details', }), getXAccessorHelp: () => i18n.translate('expressionXY.dataLayer.xAccessor.help', { @@ -233,8 +233,8 @@ export const strings = { i18n.translate('expressionXY.annotationLayer.help', { defaultMessage: `Configure an annotation layer in the xy chart`, }), - getAnnotationLayerHideHelp: () => - i18n.translate('expressionXY.annotationLayer.hide.help', { + getAnnotationLayerSimpleViewHelp: () => + i18n.translate('expressionXY.annotationLayer.simpleView.help', { defaultMessage: 'Show / hide details', }), getAnnotationLayerAnnotationsHelp: () => diff --git a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts index 8da796c811a68..5d518c31513ae 100644 --- a/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_xy/common/types/expression_functions.ts @@ -115,7 +115,7 @@ export interface DataLayerArgs { accessors: Array; seriesType: SeriesType; xAccessor?: string | ExpressionValueVisDimension; - hide?: boolean; + simpleView?: boolean; splitAccessors?: Array; markSizeAccessor?: string | ExpressionValueVisDimension; lineWidth?: number; @@ -141,7 +141,7 @@ export interface ExtendedDataLayerArgs { accessors: string[]; seriesType: SeriesType; xAccessor?: string; - hide?: boolean; + simpleView?: boolean; splitAccessors?: string[]; markSizeAccessor?: string; lineWidth?: number; @@ -280,7 +280,7 @@ export interface XYProps { export interface AnnotationLayerArgs { annotations: EventAnnotationOutput[]; - hide?: boolean; + simpleView?: boolean; } export type ExtendedAnnotationLayerArgs = AnnotationLayerArgs & { diff --git a/src/plugins/chart_expressions/expression_xy/public/__mocks__/index.tsx b/src/plugins/chart_expressions/expression_xy/public/__mocks__/index.tsx index d4781db0ff915..2e5f3163772ae 100644 --- a/src/plugins/chart_expressions/expression_xy/public/__mocks__/index.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/__mocks__/index.tsx @@ -164,7 +164,7 @@ export const dateHistogramLayer: DataLayerConfig = { type: 'dataLayer', layerType: LayerTypes.DATA, showLines: true, - hide: false, + simpleView: false, xAccessor: 'xAccessorId', xScaleType: 'time', isHistogram: true, diff --git a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap index 46bbe4c5b5a43..24c7d68cd6fda 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_xy/public/components/__snapshots__/xy_chart.test.tsx.snap @@ -208,7 +208,7 @@ exports[`XYChart component annotations should render grouped line annotations wi /> `; -exports[`XYChart component annotations should render simplified annotations when hide is true 1`] = ` +exports[`XYChart component annotations should render simplified annotations when simpleView is true 1`] = ` `; -exports[`XYChart component annotations should render simplified annotations when hide is true 2`] = ` +exports[`XYChart component annotations should render simplified annotations when simpleView is true 2`] = ` Array [ >; - hide?: boolean; + simpleView?: boolean; minInterval?: number; isBarChart?: boolean; outsideDimension: number; @@ -179,7 +179,7 @@ export const Annotations = ({ formatter, isHorizontal, paddingMap, - hide, + simpleView, minInterval, isBarChart, outsideDimension, @@ -198,7 +198,7 @@ export const Annotations = ({ const header = formatter?.convert(isGrouped ? roundedTimestamp : exactTimestamp) || moment(isGrouped ? roundedTimestamp : exactTimestamp).toISOString(); - const strokeWidth = hide ? 1 : annotation.lineWidth || 1; + const strokeWidth = simpleView ? 1 : annotation.lineWidth || 1; const dataValue = isGrouped ? moment( isBarChart && minInterval ? roundedTimestamp + minInterval / 2 : roundedTimestamp @@ -210,7 +210,7 @@ export const Annotations = ({ key={id} domainType={AnnotationDomainType.XDomain} marker={ - !hide ? ( + !simpleView ? ( { layerId: 'numberLayer', type: 'dataLayer', layerType: LayerTypes.DATA, - hide: false, + simpleView: false, showLines: true, xAccessor: 'xAccessorId', xScaleType: 'linear', @@ -1251,7 +1251,7 @@ describe('XYChart component', () => { type: 'dataLayer', layerType: LayerTypes.DATA, showLines: true, - hide: false, + simpleView: false, xAccessor: 'xAccessorId', xScaleType: 'linear', isHistogram: true, @@ -3094,11 +3094,11 @@ describe('XYChart component', () => { const component = mount(); expect(component.find(RectAnnotation)).toMatchSnapshot(); }); - test('should render simplified annotations when hide is true', () => { + test('should render simplified annotations when simpleView is true', () => { const { args } = sampleArgsWithAnnotations([ createLayerWithAnnotations([defaultLineStaticAnnotation, defaultRangeStaticAnnotation]), ]); - (args.layers[1] as CommonXYAnnotationLayerConfig).hide = true; + (args.layers[1] as CommonXYAnnotationLayerConfig).simpleView = true; const component = mount(); expect(component.find('LineAnnotation')).toMatchSnapshot(); expect(component.find('RectAnnotation')).toMatchSnapshot(); diff --git a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx index 00478aa9ddd6b..5bb7f5d6f8c47 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/xy_chart.tsx @@ -360,7 +360,7 @@ export function XYChart({ ...groupedLineAnnotations, ].filter(Boolean); - const shouldHideDetails = annotationsLayers.length > 0 ? annotationsLayers[0].hide : false; + const shouldHideDetails = annotationsLayers.length > 0 ? annotationsLayers[0].simpleView : false; const linesPaddings = !shouldHideDetails ? getLinesCausedPaddings(visualConfigs, yAxesMap, shouldRotate) : {}; @@ -740,7 +740,7 @@ export function XYChart({ } title={xTitle} gridLine={gridLineStyle} - hide={xAxisConfig?.hide || dataLayers[0]?.hide || !dataLayers[0]?.xAccessor} + hide={xAxisConfig?.hide || dataLayers[0]?.simpleView || !dataLayers[0]?.xAccessor} tickFormat={(d) => { let value = safeXAccessorLabelRenderer(d) || ''; if (xAxisConfig?.truncate && value.length > xAxisConfig.truncate) { @@ -773,7 +773,7 @@ export function XYChart({ gridLine={{ visible: axis.showGridLines, }} - hide={axis.hide || dataLayers[0]?.hide} + hide={axis.hide || dataLayers[0]?.simpleView} tickFormat={(d) => { let value = axis.formatter?.convert(d) || ''; if (axis.truncate && value.length > axis.truncate) { @@ -848,7 +848,7 @@ export function XYChart({ paddingMap={linesPaddings} isBarChart={filteredBarLayers.length > 0} minInterval={minInterval} - hide={annotationsLayers?.[0].hide} + simpleView={annotationsLayers?.[0].simpleView} outsideDimension={ rangeAnnotations.length && shouldHideDetails ? OUTSIDE_RECT_ANNOTATION_WIDTH_SUGGESTION diff --git a/src/plugins/console/public/application/components/network_request_status_bar/network_request_status_bar.tsx b/src/plugins/console/public/application/components/network_request_status_bar/network_request_status_bar.tsx index d5d8d97a4712a..320b0bbfee473 100644 --- a/src/plugins/console/public/application/components/network_request_status_bar/network_request_status_bar.tsx +++ b/src/plugins/console/public/application/components/network_request_status_bar/network_request_status_bar.tsx @@ -80,7 +80,10 @@ export const NetworkRequestStatusBar: FunctionComponent = ({ }`} } > - + {/* Use   to ensure that no matter the width we don't allow line breaks */} {statusCode} - {statusText} diff --git a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx index e999c079b490f..76e91baa8e21e 100644 --- a/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx +++ b/src/plugins/console/public/application/containers/editor/legacy/console_editor/editor.tsx @@ -233,6 +233,8 @@ function EditorUI({ initialTextValue, setEditorInstance }: EditorProps) { autocompleteInfo.clearSubscriptions(); window.removeEventListener('hashchange', onHashChange); if (editorInstanceRef.current) { + // Close autocomplete popup on unmount + editorInstanceRef.current?.getCoreEditor().detachCompleter(); editorInstanceRef.current.getCoreEditor().destroy(); } }; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts b/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts index 2208de4a9dff3..45d6eb42a9693 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts +++ b/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts @@ -228,6 +228,10 @@ export class LegacyCoreEditor implements CoreEditor { ); } + detachCompleter() { + return (this.editor as unknown as { completer: { detach(): void } }).completer.detach(); + } + private forceRetokenize() { const session = this.editor.getSession(); return new Promise((resolve) => { diff --git a/src/plugins/console/public/types/core_editor.ts b/src/plugins/console/public/types/core_editor.ts index aa048256421bb..1c9d6352914a2 100644 --- a/src/plugins/console/public/types/core_editor.ts +++ b/src/plugins/console/public/types/core_editor.ts @@ -288,4 +288,9 @@ export interface CoreEditor { * Add folds at given ranges */ addFoldsAtRanges(foldRanges: Range[]): void; + + /** + * Detach autocomplete + */ + detachCompleter(): void; } diff --git a/src/plugins/console/server/lib/proxy_request.test.ts b/src/plugins/console/server/lib/proxy_request.test.ts index 98c63d9685c87..10f43e0a8f11b 100644 --- a/src/plugins/console/server/lib/proxy_request.test.ts +++ b/src/plugins/console/server/lib/proxy_request.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import http, { ClientRequest } from 'http'; +import http, { ClientRequest, OutgoingHttpHeaders } from 'http'; import * as sinon from 'sinon'; import { proxyRequest } from './proxy_request'; import { URL } from 'url'; @@ -29,6 +29,28 @@ describe(`Console's send request`, () => { fakeRequest = null as any; }); + const sendProxyRequest = async ({ + headers = {}, + uri = new URL('http://noone.nowhere.none'), + timeout = 3000, + requestPath = '', + }: { + headers?: OutgoingHttpHeaders; + uri?: URL; + timeout?: number; + requestPath?: string; + }) => { + return await proxyRequest({ + agent: null as any, + headers, + method: 'get', + payload: null as any, + uri, + timeout, + requestPath, + }); + }; + it('correctly implements timeout and abort mechanism', async () => { fakeRequest = { destroy: sinon.stub(), @@ -36,14 +58,7 @@ describe(`Console's send request`, () => { once() {}, } as any; try { - await proxyRequest({ - agent: null as any, - headers: {}, - method: 'get', - payload: null as any, - timeout: 0, // immediately timeout - uri: new URL('http://noone.nowhere.none'), - }); + await sendProxyRequest({ timeout: 0 }); // immediately timeout fail('Should not reach here!'); } catch (e) { expect(e.message).toEqual('Client request timeout'); @@ -63,16 +78,9 @@ describe(`Console's send request`, () => { } as any; // Don't set a host header this time - const result1 = await proxyRequest({ - agent: null as any, - headers: {}, - method: 'get', - payload: null as any, - timeout: 30000, - uri: new URL('http://noone.nowhere.none'), - }); + const defaultResult = await sendProxyRequest({}); - expect(result1).toEqual('done'); + expect(defaultResult).toEqual('done'); const [httpRequestOptions1] = stub.firstCall.args; @@ -83,16 +91,9 @@ describe(`Console's send request`, () => { }); // Set a host header - const result2 = await proxyRequest({ - agent: null as any, - headers: { Host: 'myhost' }, - method: 'get', - payload: null as any, - timeout: 30000, - uri: new URL('http://noone.nowhere.none'), - }); + const resultWithHostHeader = await sendProxyRequest({ headers: { Host: 'myhost' } }); - expect(result2).toEqual('done'); + expect(resultWithHostHeader).toEqual('done'); const [httpRequestOptions2] = stub.secondCall.args; expect((httpRequestOptions2 as any).headers).toEqual({ @@ -102,7 +103,7 @@ describe(`Console's send request`, () => { }); }); - describe('with percent-encoded uri pathname', () => { + describe('with request path', () => { beforeEach(() => { fakeRequest = { abort: sinon.stub(), @@ -115,39 +116,45 @@ describe(`Console's send request`, () => { } as any; }); - it('should decode percent-encoded uri pathname and encode it correctly', async () => { - const uri = new URL( - `http://noone.nowhere.none/%{[@metadata][beat]}-%{[@metadata][version]}-2020.08.23` - ); - const result = await proxyRequest({ - agent: null as any, - headers: {}, - method: 'get', - payload: null as any, - timeout: 30000, + const verifyRequestPath = async ({ + initialPath, + expectedPath, + uri, + }: { + initialPath: string; + expectedPath: string; + uri?: URL; + }) => { + const result = await sendProxyRequest({ + requestPath: initialPath, uri, }); - expect(result).toEqual('done'); const [httpRequestOptions] = stub.firstCall.args; - expect((httpRequestOptions as any).path).toEqual( - '/%25%7B%5B%40metadata%5D%5Bbeat%5D%7D-%25%7B%5B%40metadata%5D%5Bversion%5D%7D-2020.08.23' - ); + expect((httpRequestOptions as any).path).toEqual(expectedPath); + }; + + it('should correctly encode invalid URL characters included in path', async () => { + await verifyRequestPath({ + initialPath: '%{[@metadata][beat]}-%{[@metadata][version]}-2020.08.23', + expectedPath: + '%25%7B%5B%40metadata%5D%5Bbeat%5D%7D-%25%7B%5B%40metadata%5D%5Bversion%5D%7D-2020.08.23', + }); }); - it('should issue request with date-math format', async () => { - const result = await proxyRequest({ - agent: null as any, - headers: {}, - method: 'get', - payload: null as any, - timeout: 30000, - uri: new URL(`http://noone.nowhere.none/%3Cmy-index-%7Bnow%2Fd%7D%3E`), + it('should not encode the path if it is encoded', async () => { + await verifyRequestPath({ + initialPath: '%3Cmy-index-%7Bnow%2Fd%7D%3E', + expectedPath: '%3Cmy-index-%7Bnow%2Fd%7D%3E', }); + }); - expect(result).toEqual('done'); - const [httpRequestOptions] = stub.firstCall.args; - expect((httpRequestOptions as any).path).toEqual('/%3Cmy-index-%7Bnow%2Fd%7D%3E'); + it('should correctly encode path with query params', async () => { + await verifyRequestPath({ + initialPath: '_index/.test', + uri: new URL('http://noone.nowhere.none/_index/.test?q=something&v=something'), + expectedPath: '_index/.test?q=something&v=something', + }); }); }); }); diff --git a/src/plugins/console/server/lib/proxy_request.ts b/src/plugins/console/server/lib/proxy_request.ts index 4a8839d1d8583..35452b4f99703 100644 --- a/src/plugins/console/server/lib/proxy_request.ts +++ b/src/plugins/console/server/lib/proxy_request.ts @@ -11,8 +11,9 @@ import https from 'https'; import net from 'net'; import stream from 'stream'; import Boom from '@hapi/boom'; -import { URL, URLSearchParams } from 'url'; -import { trimStart } from 'lodash'; +import { URL } from 'url'; + +import { encodePath } from './utils'; interface Args { method: 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head'; @@ -22,6 +23,7 @@ interface Args { timeout: number; headers: http.OutgoingHttpHeaders; rejectUnauthorized?: boolean; + requestPath: string; } /** @@ -31,22 +33,6 @@ interface Args { const sanitizeHostname = (hostName: string): string => hostName.trim().replace(/^\[/, '').replace(/\]$/, ''); -/** - * Node URL percent-encodes any invalid characters in the pathname which results a 400 bad request error. - * We need to decode the percent-encoded pathname, and encode it correctly with encodeURIComponent - */ - -const encodePathname = (pathname: string) => { - const decodedPath = new URLSearchParams(`path=${pathname}`).get('path') ?? ''; - - // Skip if it is valid - if (pathname === decodedPath) { - return pathname; - } - - return `/${encodeURIComponent(trimStart(decodedPath, '/'))}`; -}; - // We use a modified version of Hapi's Wreck because Hapi, Axios, and Superagent don't support GET requests // with bodies, but ES APIs do. Similarly with DELETE requests with bodies. Another library, `request` // diverged too much from current behaviour. @@ -58,10 +44,11 @@ export const proxyRequest = ({ timeout, payload, rejectUnauthorized, + requestPath, }: Args) => { - const { hostname, port, protocol, pathname, search } = uri; + const { hostname, port, protocol, search } = uri; const client = uri.protocol === 'https:' ? https : http; - const encodedPath = encodePathname(pathname); + const encodedPath = encodePath(requestPath); let resolved = false; let resolve: (res: http.IncomingMessage) => void; diff --git a/src/plugins/console/server/lib/utils/encode_path.test.ts b/src/plugins/console/server/lib/utils/encode_path.test.ts new file mode 100644 index 0000000000000..07c7108e9d2cf --- /dev/null +++ b/src/plugins/console/server/lib/utils/encode_path.test.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { encodePath } from './encode_path'; + +describe('encodePath', () => { + const tests = [ + { + description: 'encodes invalid URL characters', + source: '/%{[@metadata][beat]}-%{[@metadata][version]}-2020.08.23', + assert: + '/%25%7B%5B%40metadata%5D%5Bbeat%5D%7D-%25%7B%5B%40metadata%5D%5Bversion%5D%7D-2020.08.23', + }, + { + description: 'ignores encoded characters', + source: '/my-index/_doc/this%2Fis%2Fa%2Fdoc', + assert: '/my-index/_doc/this%2Fis%2Fa%2Fdoc', + }, + { + description: 'ignores slashes between', + source: '_index/test/.test', + assert: '_index/test/.test', + }, + ]; + + tests.forEach(({ description, source, assert }) => { + test(description, () => { + const result = encodePath(source); + expect(result).toEqual(assert); + }); + }); +}); diff --git a/src/plugins/console/server/lib/utils/encode_path.ts b/src/plugins/console/server/lib/utils/encode_path.ts new file mode 100644 index 0000000000000..273c60d3f66e4 --- /dev/null +++ b/src/plugins/console/server/lib/utils/encode_path.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { URLSearchParams } from 'url'; +import { trimStart } from 'lodash'; + +export const encodePath = (path: string) => { + const decodedPath = new URLSearchParams(`path=${path}`).get('path') ?? ''; + // Take the initial path and compare it with the decoded path. + // If the result is not the same, the path is encoded. + const isEncoded = trimStart(path, '/') !== trimStart(decodedPath, '/'); + + // Return the initial path if it is already encoded + if (isEncoded) { + return path; + } + + // Encode every component except slashes + return path + .split('/') + .map((component) => encodeURIComponent(component)) + .join('/'); +}; diff --git a/src/plugins/console/server/lib/utils/index.ts b/src/plugins/console/server/lib/utils/index.ts new file mode 100644 index 0000000000000..19c35901570e6 --- /dev/null +++ b/src/plugins/console/server/lib/utils/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { encodePath } from './encode_path'; diff --git a/src/plugins/console/server/routes/api/console/proxy/create_handler.ts b/src/plugins/console/server/routes/api/console/proxy/create_handler.ts index 1fc22ca685cc5..2e575c7723a64 100644 --- a/src/plugins/console/server/routes/api/console/proxy/create_handler.ts +++ b/src/plugins/console/server/routes/api/console/proxy/create_handler.ts @@ -145,6 +145,10 @@ export const createHandler = const host = hosts[idx]; try { const uri = toURL(host, path); + // Invalid URL characters included in uri pathname will be percent-encoded by Node URL method, and results in a faulty request in some cases. + // To fix this issue, we need to extract the original request path and supply it to proxyRequest function to encode it correctly with encodeURIComponent. + // We ignore the search params here, since we are extracting them from the uri constructed by Node URL method. + const [requestPath] = path.split('?'); // Because this can technically be provided by a settings-defined proxy config, we need to // preserve these property names to maintain BWC. @@ -174,6 +178,7 @@ export const createHandler = payload: body, rejectUnauthorized, agent, + requestPath, }); break; diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx index 7726258b399e2..318db746fbe42 100644 --- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx +++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx @@ -107,12 +107,16 @@ export class DashboardViewport extends React.Component {controlsEnabled ? ( <> - {isEditMode && panelCount !== 0 && controlGroup?.getPanelCount() === 0 ? ( + {!hideAnnouncements && + isEditMode && + panelCount !== 0 && + controlGroup?.getPanelCount() === 0 ? ( { return controlGroup?.getCreateControlButton('callout'); diff --git a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx index 744e3824e3c68..3c1305d8e7860 100644 --- a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx +++ b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx @@ -193,10 +193,11 @@ const IndexPatternEditorFlyoutContentComponent = ({ useEffect(() => { loadSources(); const getTitles = async () => { - const indexPatternTitles = await dataViews.getTitles(editData ? true : false); + const dataViewListItems = await dataViews.getIdsWithTitle(editData ? true : false); + const indexPatternNames = dataViewListItems.map((item) => item.name || item.title); setExistingIndexPatterns( - editData ? indexPatternTitles.filter((v) => v !== editData.title) : indexPatternTitles + editData ? indexPatternNames.filter((v) => v !== editData.name) : indexPatternNames ); setIsLoadingIndexPatterns(false); }; @@ -226,9 +227,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ const currentLoadingTimestampFieldsIdx = ++currentLoadingTimestampFieldsRef.current; let timestampOptions: TimestampOption[] = []; const isValidResult = - !existingIndexPatterns.includes(query) && - matchedIndices.exactMatchedIndices.length > 0 && - !isLoadingMatchedIndices; + matchedIndices.exactMatchedIndices.length > 0 && !isLoadingMatchedIndices; if (isValidResult) { setIsLoadingTimestampFields(true); const getFieldsOptions: GetFieldsOptions = { @@ -249,7 +248,6 @@ const IndexPatternEditorFlyoutContentComponent = ({ return timestampOptions; }, [ - existingIndexPatterns, dataViews, requireTimestampField, rollupIndex, @@ -380,7 +378,7 @@ const IndexPatternEditorFlyoutContentComponent = ({ - + @@ -388,7 +386,6 @@ const IndexPatternEditorFlyoutContentComponent = ({ diff --git a/src/plugins/data_view_editor/public/components/form_fields/name_field.tsx b/src/plugins/data_view_editor/public/components/form_fields/name_field.tsx index 8b6a0cfb74b70..f2236abad5ec7 100644 --- a/src/plugins/data_view_editor/public/components/form_fields/name_field.tsx +++ b/src/plugins/data_view_editor/public/components/form_fields/name_field.tsx @@ -6,20 +6,66 @@ * Side Public License, v 1. */ -import React, { ChangeEvent } from 'react'; +import React, { ChangeEvent, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiFieldText } from '@elastic/eui'; -import { DataView, UseField } from '../../shared_imports'; +import { + DataView, + UseField, + ValidationConfig, + FieldConfig, + getFieldValidityAndErrorMessage, +} from '../../shared_imports'; import { IndexPatternConfig } from '../../types'; +import { schema } from '../form_schema'; interface NameFieldProps { editData?: DataView; + existingDataViewNames: string[]; } -export const NameField = ({ editData }: NameFieldProps) => { +interface GetNameConfigArgs { + namesNotAllowed: string[]; +} + +const createNameNoDupesValidator = ( + namesNotAllowed: string[] +): ValidationConfig<{}, string, string> => ({ + validator: ({ value }) => { + if (namesNotAllowed.includes(value)) { + return { + message: i18n.translate('indexPatternEditor.dataViewExists.ValidationErrorMessage', { + defaultMessage: 'A data view with this name already exists.', + }), + }; + } + }, +}); + +const getNameConfig = ({ namesNotAllowed }: GetNameConfigArgs): FieldConfig => { + const nameFieldConfig = schema.name; + + const validations = [...nameFieldConfig.validations, createNameNoDupesValidator(namesNotAllowed)]; + + return { + ...nameFieldConfig!, + validations, + }; +}; + +export const NameField = ({ editData, existingDataViewNames }: NameFieldProps) => { + const config = useMemo( + () => + getNameConfig({ + namesNotAllowed: existingDataViewNames, + }), + [existingDataViewNames] + ); + return ( path="name" + config={config} componentProps={{ euiFieldProps: { 'aria-label': i18n.translate('indexPatternEditor.form.nameAriaLabel', { @@ -29,8 +75,9 @@ export const NameField = ({ editData }: NameFieldProps) => { }} > {(field) => { + const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); return ( - + ) => { diff --git a/src/plugins/data_view_editor/public/components/form_fields/timestamp_field.tsx b/src/plugins/data_view_editor/public/components/form_fields/timestamp_field.tsx index dd9d4f7117453..ce36d1e1fdc99 100644 --- a/src/plugins/data_view_editor/public/components/form_fields/timestamp_field.tsx +++ b/src/plugins/data_view_editor/public/components/form_fields/timestamp_field.tsx @@ -24,7 +24,6 @@ import { schema } from '../form_schema'; interface Props { options: TimestampOption[]; isLoadingOptions: boolean; - isExistingIndexPattern: boolean; isLoadingMatchedIndices: boolean; hasMatchedIndices: boolean; } @@ -73,7 +72,6 @@ const timestampFieldHelp = i18n.translate('indexPatternEditor.editor.form.timeFi export const TimestampField = ({ options = [], isLoadingOptions = false, - isExistingIndexPattern, isLoadingMatchedIndices, hasMatchedIndices, }: Props) => { @@ -85,11 +83,7 @@ export const TimestampField = ({ const selectTimestampHelp = options.length ? timestampFieldHelp : ''; const timestampNoFieldsHelp = - options.length === 0 && - !isExistingIndexPattern && - !isLoadingMatchedIndices && - !isLoadingOptions && - hasMatchedIndices + options.length === 0 && !isLoadingMatchedIndices && !isLoadingOptions && hasMatchedIndices ? noTimestampOptionText : ''; diff --git a/src/plugins/data_view_editor/public/components/form_fields/title_field.tsx b/src/plugins/data_view_editor/public/components/form_fields/title_field.tsx index 29bb64bb53997..6c41700ead531 100644 --- a/src/plugins/data_view_editor/public/components/form_fields/title_field.tsx +++ b/src/plugins/data_view_editor/public/components/form_fields/title_field.tsx @@ -30,7 +30,6 @@ interface RefreshMatchedIndicesResult { } interface TitleFieldProps { - existingIndexPatterns: string[]; isRollup: boolean; matchedIndices: MatchedItem[]; rollupIndicesCapabilities: RollupIndicesCapsResponse; @@ -55,20 +54,6 @@ const mustMatchError = { }), }; -const createTitlesNoDupesValidator = ( - namesNotAllowed: string[] -): ValidationConfig<{}, string, string> => ({ - validator: ({ value }) => { - if (namesNotAllowed.includes(value)) { - return { - message: i18n.translate('indexPatternEditor.dataViewExists.ValidationErrorMessage', { - defaultMessage: 'An index pattern with this name already exists.', - }), - }; - } - }, -}); - interface MatchesValidatorArgs { rollupIndicesCapabilities: Record; refreshMatchedIndices: (title: string) => Promise; @@ -122,7 +107,6 @@ const createMatchesIndicesValidator = ({ }); interface GetTitleConfigArgs { - namesNotAllowed: string[]; isRollup: boolean; matchedIndices: MatchedItem[]; rollupIndicesCapabilities: RollupIndicesCapsResponse; @@ -130,7 +114,6 @@ interface GetTitleConfigArgs { } const getTitleConfig = ({ - namesNotAllowed, isRollup, rollupIndicesCapabilities, refreshMatchedIndices, @@ -145,7 +128,6 @@ const getTitleConfig = ({ refreshMatchedIndices, isRollup, }), - createTitlesNoDupesValidator(namesNotAllowed), ]; return { @@ -155,7 +137,6 @@ const getTitleConfig = ({ }; export const TitleField = ({ - existingIndexPatterns, isRollup, matchedIndices, rollupIndicesCapabilities, @@ -166,19 +147,12 @@ export const TitleField = ({ const fieldConfig = useMemo( () => getTitleConfig({ - namesNotAllowed: existingIndexPatterns, isRollup, matchedIndices, rollupIndicesCapabilities, refreshMatchedIndices, }), - [ - existingIndexPatterns, - isRollup, - matchedIndices, - rollupIndicesCapabilities, - refreshMatchedIndices, - ] + [isRollup, matchedIndices, rollupIndicesCapabilities, refreshMatchedIndices] ); return ( diff --git a/src/plugins/data_view_editor/public/components/form_schema.ts b/src/plugins/data_view_editor/public/components/form_schema.ts index 9af41592dcbfe..98c3a3b5322eb 100644 --- a/src/plugins/data_view_editor/public/components/form_schema.ts +++ b/src/plugins/data_view_editor/public/components/form_schema.ts @@ -50,6 +50,7 @@ export const schema = { defaultMessage: 'Name', }), defaultValue: '', + validations: [], }, timestampField: { label: i18n.translate('indexPatternEditor.editor.form.timeFieldLabel', { diff --git a/src/plugins/data_view_editor/public/lib/get_indices.ts b/src/plugins/data_view_editor/public/lib/get_indices.ts index 0ddd75fa688be..83b64916cdae9 100644 --- a/src/plugins/data_view_editor/public/lib/get_indices.ts +++ b/src/plugins/data_view_editor/public/lib/get_indices.ts @@ -9,7 +9,6 @@ import { sortBy } from 'lodash'; import { HttpStart } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; -import { IEsSearchResponse } from '@kbn/data-plugin/public'; import { Tag, INDEX_PATTERN_TYPE } from '../types'; import { MatchedItem, ResolveIndexResponse, ResolveIndexResponseItemIndexAttrs } from '../types'; @@ -41,35 +40,6 @@ const getIndexTags = (isRollupIndex: (indexName: string) => boolean) => (indexNa ] : []; -export const searchResponseToArray = - (getTags: (indexName: string) => Tag[], showAllIndices: boolean) => - (response: IEsSearchResponse) => { - const { rawResponse } = response; - if (!rawResponse.aggregations) { - return []; - } else { - // @ts-expect-error @elastic/elasticsearch no way to declare a type for aggregation in the search response - return rawResponse.aggregations.indices.buckets - .map((bucket: { key: string }) => { - return bucket.key; - }) - .filter((indexName: string) => { - if (showAllIndices) { - return true; - } else { - return !indexName.startsWith('.'); - } - }) - .map((indexName: string) => { - return { - name: indexName, - tags: getTags(indexName), - item: {}, - }; - }); - } - }; - export const getIndicesViaResolve = async ({ http, pattern, diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/bytes/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/bytes/index.ts index 5d631e22a8890..9968cba5020c0 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/bytes/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/bytes/index.ts @@ -7,8 +7,9 @@ */ import { formatId } from './constants'; import { FieldFormatEditorFactory } from '../types'; +import { NumberFormatEditorParams } from '../number/number'; export type { BytesFormatEditor } from './bytes'; -export const bytesFormatEditorFactory: FieldFormatEditorFactory = () => +export const bytesFormatEditorFactory: FieldFormatEditorFactory = () => import('./bytes').then((m) => m.BytesFormatEditor); bytesFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/color/color.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/color/color.tsx index 8418f24bd443f..c7af24fc772e8 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/color/color.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/color/color.tsx @@ -29,7 +29,7 @@ interface IndexedColor extends Color { index: number; } -interface ColorFormatEditorFormatParams { +export interface ColorFormatEditorFormatParams { colors: Color[]; } @@ -38,8 +38,8 @@ export class ColorFormatEditor extends DefaultFormatEditor) { super(props); this.onChange({ - fieldType: props.fieldType, - }); + fieldType: props.fieldType, // FIXME: why add `fieldType` as an EditorFormatParam? + } as unknown as ColorFormatEditorFormatParams); } onColorChange = (newColorParams: Partial, index: number) => { diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/color/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/color/index.ts index b6cadb8aae43b..5b49cbfc57398 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/color/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/color/index.ts @@ -7,9 +7,11 @@ */ import { FieldFormatEditorFactory } from '../types'; +import { ColorFormatEditorFormatParams } from './color'; import { formatId } from './constants'; export type { ColorFormatEditor } from './color'; -export const colorFormatEditorFactory: FieldFormatEditorFactory = () => - import('./color').then((m) => m.ColorFormatEditor); +export const colorFormatEditorFactory: FieldFormatEditorFactory< + ColorFormatEditorFormatParams +> = () => import('./color').then((m) => m.ColorFormatEditor); colorFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date/date.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date/date.tsx index fdf0291f0fa4d..ed294c980d85d 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date/date.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date/date.tsx @@ -17,7 +17,7 @@ import { formatId } from './constants'; import { FormatEditorSamples } from '../../samples'; -interface DateFormatEditorFormatParams { +export interface DateFormatEditorFormatParams { pattern: string; } diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date/index.ts index 9fb47b285f669..2f4a14eee3696 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date/index.ts @@ -8,8 +8,9 @@ import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; +import { DateFormatEditorFormatParams } from './date'; export type { DateFormatEditor } from './date'; -export const dateFormatEditorFactory: FieldFormatEditorFactory = () => +export const dateFormatEditorFactory: FieldFormatEditorFactory = () => import('./date').then((m) => m.DateFormatEditor); dateFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date_nanos/date_nanos.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date_nanos/date_nanos.tsx index 468263fcdfc38..24b20f2351f01 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date_nanos/date_nanos.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date_nanos/date_nanos.tsx @@ -16,7 +16,7 @@ import { formatId } from './constants'; import { FormatEditorSamples } from '../../samples'; -interface DateNanosFormatEditorFormatParams { +export interface DateNanosFormatEditorFormatParams { pattern: string; } diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date_nanos/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date_nanos/index.ts index ade21b27f60ef..3102ae326670f 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date_nanos/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/date_nanos/index.ts @@ -8,8 +8,10 @@ import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; +import { DateNanosFormatEditorFormatParams } from './date_nanos'; export type { DateNanosFormatEditor } from './date_nanos'; -export const dateNanosFormatEditorFactory: FieldFormatEditorFactory = () => - import('./date_nanos').then((m) => m.DateNanosFormatEditor); +export const dateNanosFormatEditorFactory: FieldFormatEditorFactory< + DateNanosFormatEditorFormatParams +> = () => import('./date_nanos').then((m) => m.DateNanosFormatEditor); dateNanosFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx index a3a71becb3ef3..30ef104df9b5f 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import React, { PureComponent, ReactText } from 'react'; -import { i18n } from '@kbn/i18n'; - import type { FieldFormatsContentType } from '@kbn/field-formats-plugin/common'; +import { i18n } from '@kbn/i18n'; +import React, { PureComponent, ReactText } from 'react'; import type { Sample, SampleInput } from '../../types'; import type { FormatEditorProps } from '../types'; import { formatId } from './constants'; @@ -80,7 +79,7 @@ export class DefaultFormatEditor

extends PureComponent< return output; } - onChange = (newParams = {}) => { + onChange = (newParams = {} as Partial['formatParams']>) => { const { onChange, formatParams } = this.props; onChange({ diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/duration/duration.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/duration/duration.tsx index 8b8864622ffc2..f1a6f8089f70d 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/duration/duration.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/duration/duration.tsx @@ -33,8 +33,8 @@ interface OutputFormat { text: string; } -interface DurationFormatEditorFormatParams { - outputPrecision: number; +export interface DurationFormatEditorFormatParams { + outputPrecision: number | null; inputFormat: string; outputFormat: string; showSuffix?: boolean; @@ -60,9 +60,11 @@ export class DurationFormatEditor extends DefaultFormatEditor< const output = super.getDerivedStateFromProps(nextProps, state); let error = null; + const { outputPrecision } = nextProps.formatParams; if ( !(nextProps.format as DurationFormat).isHuman() && - nextProps.formatParams.outputPrecision > 20 + outputPrecision != null && + outputPrecision > 20 ) { error = i18n.translate('indexPatternFieldEditor.durationErrorMessage', { defaultMessage: 'Decimal places must be between 0 and 20', @@ -156,7 +158,7 @@ export class DurationFormatEditor extends DefaultFormatEditor< error={hasDecimalError ? error : null} > { diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/duration/index.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/duration/index.tsx index 8e489fbb2a464..40163675aa16f 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/duration/index.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/duration/index.tsx @@ -8,8 +8,10 @@ import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; +import { DurationFormatEditorFormatParams } from './duration'; export type { DurationFormatEditor } from './duration'; -export const durationFormatEditorFactory: FieldFormatEditorFactory = () => - import('./duration').then((m) => m.DurationFormatEditor); +export const durationFormatEditorFactory: FieldFormatEditorFactory< + DurationFormatEditorFormatParams +> = () => import('./duration').then((m) => m.DurationFormatEditor); durationFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/geo_point/geo_point.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/geo_point/geo_point.tsx index a9460b7e045ca..bf49318e8d62f 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/geo_point/geo_point.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/geo_point/geo_point.tsx @@ -17,7 +17,7 @@ import { DefaultFormatEditor, defaultState } from '../default/default'; import { FormatEditorSamples } from '../../samples'; import { formatId } from './constants'; -interface GeoPointFormatEditorFormatParams { +export interface GeoPointFormatEditorFormatParams { transform: string; } diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/geo_point/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/geo_point/index.ts index c7eddd167ba91..525157a231126 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/geo_point/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/geo_point/index.ts @@ -8,8 +8,10 @@ import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; +import { GeoPointFormatEditorFormatParams } from './geo_point'; export type { GeoPointFormatEditor } from './geo_point'; -export const geoPointFormatEditorFactory: FieldFormatEditorFactory = () => - import('./geo_point').then((m) => m.GeoPointFormatEditor); +export const geoPointFormatEditorFactory: FieldFormatEditorFactory< + GeoPointFormatEditorFormatParams +> = () => import('./geo_point').then((m) => m.GeoPointFormatEditor); geoPointFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/histogram/histogram.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/histogram/histogram.tsx index ee99c03279aed..7caa0d4429803 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/histogram/histogram.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/histogram/histogram.tsx @@ -67,7 +67,7 @@ export class HistogramFormatEditor extends DefaultFormatEditor { - this.onChange({ id: e.target.value }); + this.onChange({ id: e.target.value as HistogramFormatEditorParams['id'] }); }} /> diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/histogram/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/histogram/index.ts index 071581893f9d9..b66047b65fce9 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/histogram/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/histogram/index.ts @@ -8,8 +8,10 @@ import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; +import { HistogramFormatEditorParams } from './histogram'; export type { HistogramFormatEditor } from './histogram'; -export const histogramFormatEditorFactory: FieldFormatEditorFactory = () => - import('./histogram').then((m) => m.HistogramFormatEditor); +export const histogramFormatEditorFactory: FieldFormatEditorFactory< + HistogramFormatEditorParams +> = () => import('./histogram').then((m) => m.HistogramFormatEditor); histogramFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/index.ts index 4d40544cf7c37..18ac46228d912 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/index.ts @@ -6,20 +6,21 @@ * Side Public License, v 1. */ +export type { DefaultFormatEditor } from './default'; export type { FieldFormatEditor, FieldFormatEditorFactory, FormatEditorProps } from './types'; - -export { DefaultFormatEditor, defaultFormatEditorFactory } from './default'; +export type { UrlFormatEditorFormatParams } from './url'; export { BytesFormatEditor, bytesFormatEditorFactory } from './bytes'; export { ColorFormatEditor, colorFormatEditorFactory } from './color'; export { DateFormatEditor, dateFormatEditorFactory } from './date'; export { DateNanosFormatEditor, dateNanosFormatEditorFactory } from './date_nanos'; +export { defaultFormatEditorFactory } from './default'; export { DurationFormatEditor, durationFormatEditorFactory } from './duration'; export { GeoPointFormatEditor, geoPointFormatEditorFactory } from './geo_point'; +export { HistogramFormatEditor, histogramFormatEditorFactory } from './histogram'; export { NumberFormatEditor, numberFormatEditorFactory } from './number'; export { PercentFormatEditor, percentFormatEditorFactory } from './percent'; export { StaticLookupFormatEditor, staticLookupFormatEditorFactory } from './static_lookup'; export { StringFormatEditor, stringFormatEditorFactory } from './string'; export { TruncateFormatEditor, truncateFormatEditorFactory } from './truncate'; export { UrlFormatEditor, urlFormatEditorFactory } from './url'; -export { HistogramFormatEditor, histogramFormatEditorFactory } from './histogram'; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/number/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/number/index.ts index 7589c7b89c01b..6d0dda6170cdb 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/number/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/number/index.ts @@ -8,8 +8,9 @@ import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; +import { NumberFormatEditorParams } from './number'; export type { NumberFormatEditor } from './number'; -export const numberFormatEditorFactory: FieldFormatEditorFactory = () => +export const numberFormatEditorFactory: FieldFormatEditorFactory = () => import('./number').then((m) => m.NumberFormatEditor); numberFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/percent/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/percent/index.ts index 5fd8871f2798b..e8ecc81ba20dc 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/percent/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/percent/index.ts @@ -6,10 +6,11 @@ * Side Public License, v 1. */ +import { NumberFormatEditorParams } from '../number/number'; import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; export type { PercentFormatEditor } from './percent'; -export const percentFormatEditorFactory: FieldFormatEditorFactory = () => +export const percentFormatEditorFactory: FieldFormatEditorFactory = () => import('./percent').then((m) => m.PercentFormatEditor); percentFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/static_lookup/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/static_lookup/index.ts index 325e132e9d791..db538ae81dd39 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/static_lookup/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/static_lookup/index.ts @@ -8,8 +8,10 @@ import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; +import { StaticLookupFormatEditorFormatParams } from './static_lookup'; export type { StaticLookupFormatEditor } from './static_lookup'; -export const staticLookupFormatEditorFactory: FieldFormatEditorFactory = () => - import('./static_lookup').then((m) => m.StaticLookupFormatEditor); +export const staticLookupFormatEditorFactory: FieldFormatEditorFactory< + StaticLookupFormatEditorFormatParams +> = () => import('./static_lookup').then((m) => m.StaticLookupFormatEditor); staticLookupFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/static_lookup/static_lookup.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/static_lookup/static_lookup.tsx index 5b2402b240994..bb4c2a965f4ef 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/static_lookup/static_lookup.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/static_lookup/static_lookup.tsx @@ -20,6 +20,11 @@ export interface StaticLookupFormatEditorFormatParams { unknownKeyValue: string; } +interface LookupItem { + key: string; + value: string; +} + interface StaticLookupItem { key: string; value: string; @@ -42,7 +47,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor { const lookupEntries = [...(this.props.formatParams.lookupEntries || [])]; this.onChange({ - lookupEntries: [...lookupEntries, {}], + lookupEntries: [...lookupEntries, {} as LookupItem], }); }; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/string/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/string/index.ts index 194b2444c5576..001f6478d3bfc 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/string/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/string/index.ts @@ -8,8 +8,10 @@ import { FieldFormatEditorFactory } from '../types'; import { formatId } from './constants'; +import { StringFormatEditorFormatParams } from './string'; export type { StringFormatEditor } from './string'; -export const stringFormatEditorFactory: FieldFormatEditorFactory = () => - import('./string').then((m) => m.StringFormatEditor); +export const stringFormatEditorFactory: FieldFormatEditorFactory< + StringFormatEditorFormatParams +> = () => import('./string').then((m) => m.StringFormatEditor); stringFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/string/string.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/string/string.tsx index 21e48130a73d9..cf708283b94aa 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/string/string.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/string/string.tsx @@ -17,7 +17,7 @@ import { DefaultFormatEditor, defaultState } from '../default/default'; import { FormatEditorSamples } from '../../samples'; import { formatId } from './constants'; -interface StringFormatEditorFormatParams { +export interface StringFormatEditorFormatParams { transform: string; } diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/truncate/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/truncate/index.ts index 2b0cfda4dcab3..d00da9413e0d4 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/truncate/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/truncate/index.ts @@ -8,8 +8,10 @@ import { formatId } from './constants'; import { FieldFormatEditorFactory } from '../types'; +import { TruncateFormatEditorFormatParams } from './truncate'; export type { TruncateFormatEditor } from './truncate'; -export const truncateFormatEditorFactory: FieldFormatEditorFactory = () => - import('./truncate').then((m) => m.TruncateFormatEditor); +export const truncateFormatEditorFactory: FieldFormatEditorFactory< + TruncateFormatEditorFormatParams +> = () => import('./truncate').then((m) => m.TruncateFormatEditor); truncateFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/truncate/truncate.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/truncate/truncate.tsx index 5dc87cd44651f..99436eaf8b680 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/truncate/truncate.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/truncate/truncate.tsx @@ -18,8 +18,8 @@ import { FormatEditorSamples } from '../../samples'; import { sample } from './sample'; import { formatId } from './constants'; -interface TruncateFormatEditorFormatParams { - fieldLength: number; +export interface TruncateFormatEditorFormatParams { + fieldLength: number | null; } export class TruncateFormatEditor extends DefaultFormatEditor { @@ -46,7 +46,7 @@ export class TruncateFormatEditor extends DefaultFormatEditor { diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/types.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/types.ts index ceb18914ebfc0..3d02bdf9e2681 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/types.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/types.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import type { FieldFormat, FieldFormatParams } from '@kbn/field-formats-plugin/common'; import type { ComponentType } from 'react'; -import type { FieldFormat } from '@kbn/field-formats-plugin/common'; import type { FormatSelectEditorProps } from '../field_format_editor'; /** @@ -18,7 +18,7 @@ export interface FormatEditorProps

{ fieldType: string; format: FieldFormat; formatParams: { type?: string } & P; - onChange: (newParams: { [key: string]: any }) => void; + onChange: (newParams: FieldFormatParams) => void; onError: FormatSelectEditorProps['onError']; } @@ -34,7 +34,7 @@ export type FieldFormatEditor = ComponentType< * A factory for registering field format editor for a field format with `formatId` * @public */ -export type FieldFormatEditorFactory = (() => Promise< +export type FieldFormatEditorFactory = (() => Promise< FieldFormatEditor >) & { formatId: string; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/url/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/url/index.ts index 6da051003554c..c83975f2a5c23 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/url/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/url/index.ts @@ -7,9 +7,10 @@ */ import { formatId } from './constants'; import { FieldFormatEditorFactory } from '../types'; +import { UrlFormatEditorFormatParams } from './url'; -export type { UrlFormatEditor } from './url'; +export type { UrlFormatEditor, UrlFormatEditorFormatParams } from './url'; -export const urlFormatEditorFactory: FieldFormatEditorFactory = () => +export const urlFormatEditorFactory: FieldFormatEditorFactory = () => import('./url').then((m) => m.UrlFormatEditor); urlFormatEditorFactory.formatId = formatId; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/url/url.test.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/url/url.test.tsx index 8993e2a3185ce..4390d488e420a 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/url/url.test.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/editors/url/url.test.tsx @@ -9,11 +9,12 @@ import React from 'react'; import type { FieldFormat } from '@kbn/field-formats-plugin/common'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; -import { UrlFormatEditor } from './url'; +import { UrlFormatEditor, UrlFormatEditorFormatParams } from './url'; import { coreMock } from '@kbn/core/public/mocks'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { render } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { Serializable } from '@kbn/utility-types'; const fieldType = 'string'; const format = { @@ -28,7 +29,7 @@ const format = { ], }, } as unknown as FieldFormat; -const formatParams = { +const formatParams: UrlFormatEditorFormatParams = { openLinkInCurrentTab: true, urlTemplate: '', labelTemplate: '', @@ -85,7 +86,7 @@ describe('UrlFormatEditor', () => { }); it('should append base path to preview images', async () => { - let sampleImageUrlTemplate = ''; + let sampleImageUrlTemplate: Serializable = ''; const { getByLabelText } = renderWithContext( + onFormatChange = (formatId: string, params?: FieldFormatParams) => this.props.onChange( formatId ? { @@ -98,7 +96,7 @@ export class FormatSelectEditor extends PureComponent< : undefined ); - onFormatParamsChange = (newParams: { [key: string]: any }) => { + onFormatParamsChange = (newParams: FieldFormatParams) => { const { fieldFormatId } = this.state; this.onFormatChange(fieldFormatId as string, newParams); }; diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx index 2fcaa3420848a..4211047878cca 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx @@ -7,18 +7,19 @@ */ import { EuiDelayRender, EuiLoadingContent } from '@elastic/eui'; +import type { FieldFormat, FieldFormatParams } from '@kbn/field-formats-plugin/common'; import { memoize } from 'lodash'; -import React, { PureComponent, LazyExoticComponent } from 'react'; -import type { FieldFormat } from '@kbn/field-formats-plugin/common'; -import { FieldFormatEditorFactory, FieldFormatEditor } from './editors'; +import React, { LazyExoticComponent, PureComponent } from 'react'; +import { FormatEditorServiceStart } from '../../service'; +import { FieldFormatEditor, FieldFormatEditorFactory } from './editors'; export interface FormatEditorProps { fieldType: string; fieldFormat: FieldFormat; fieldFormatId: string; - fieldFormatParams: { [key: string]: unknown }; - fieldFormatEditors: any; - onChange: (change: { [key: string]: any }) => void; + fieldFormatParams: FieldFormatParams; + fieldFormatEditors: FormatEditorServiceStart['fieldFormatEditors']; + onChange: (change: FieldFormatParams) => void; onError: (error?: string) => void; } @@ -39,13 +40,15 @@ export class FormatEditor extends PureComponent { index: string; context: PainlessExecuteContext; script: { source: string } | null; - document: Record; + document: Record; }) => { return sendRequest(httpClient, { path: `${API_BASE_PATH}/field_preview`, diff --git a/src/plugins/data_view_field_editor/public/service/field_format_editors/field_format_editors.ts b/src/plugins/data_view_field_editor/public/service/field_format_editors/field_format_editors.ts index 8e3b4691b9d91..ded7243c45668 100644 --- a/src/plugins/data_view_field_editor/public/service/field_format_editors/field_format_editors.ts +++ b/src/plugins/data_view_field_editor/public/service/field_format_editors/field_format_editors.ts @@ -7,11 +7,14 @@ */ import { FieldFormatEditorFactory } from '../../components/field_format_editor'; +import { FormatEditorServiceSetup, FormatEditorServiceStart } from '../format_editor_service'; export class FieldFormatEditors { private editors: FieldFormatEditorFactory[] = []; - public setup(defaultFieldEditors: FieldFormatEditorFactory[] = []) { + public setup( + defaultFieldEditors: FieldFormatEditorFactory[] = [] + ): FormatEditorServiceSetup['fieldFormatEditors'] { this.editors = defaultFieldEditors; return { @@ -21,11 +24,13 @@ export class FieldFormatEditors { }; } - public start() { + public start(): FormatEditorServiceStart['fieldFormatEditors'] { return { getAll: () => [...this.editors], - getById: (id: string) => { - return this.editors.find((editor) => editor.formatId === id); + getById:

(id: string) => { + return this.editors.find((editor) => editor.formatId === id) as + | FieldFormatEditorFactory

+ | undefined; }, }; } diff --git a/src/plugins/data_view_field_editor/public/service/format_editor_service.ts b/src/plugins/data_view_field_editor/public/service/format_editor_service.ts index 61458820bd79f..7d385aeaacd6f 100644 --- a/src/plugins/data_view_field_editor/public/service/format_editor_service.ts +++ b/src/plugins/data_view_field_editor/public/service/format_editor_service.ts @@ -38,7 +38,7 @@ export class FormatEditorService { } public setup() { - const defaultFieldFormatEditorFactories: FieldFormatEditorFactory[] = [ + const defaultFieldFormatEditorFactories = [ bytesFormatEditorFactory, colorFormatEditorFactory, dateFormatEditorFactory, @@ -52,7 +52,7 @@ export class FormatEditorService { truncateFormatEditorFactory, urlFormatEditorFactory, histogramFormatEditorFactory, - ]; + ] as FieldFormatEditorFactory[]; const fieldFormatEditorsSetup = this.fieldFormatEditors.setup( defaultFieldFormatEditorFactories @@ -75,5 +75,16 @@ export class FormatEditorService { } /** @internal */ -export type FormatEditorServiceSetup = ReturnType; -export type FormatEditorServiceStart = ReturnType; +export interface FormatEditorServiceSetup { + fieldFormatEditors: { + register: (editor: FieldFormatEditorFactory) => void; + }; +} + +/** @internal */ +export interface FormatEditorServiceStart { + fieldFormatEditors: { + getAll: () => FieldFormatEditorFactory[]; + getById:

(id: string) => FieldFormatEditorFactory

| undefined; + }; +} diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx index d26b0726d7814..e4326439e574a 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx @@ -24,7 +24,7 @@ interface IndexedFieldsTableProps { deleteField: (fieldName: string) => void; getFieldInfo: (indexPattern: DataView, field: DataViewField) => string[]; }; - fieldWildcardMatcher: (filters: any[]) => (val: any) => boolean; + fieldWildcardMatcher: (filters: string[] | undefined) => (val: string) => boolean; userEditPermission: boolean; openModal: OverlayStart['openModal']; theme: ThemeServiceStart; @@ -57,8 +57,7 @@ export class IndexedFieldsTable extends Component< mapFields(fields: DataViewField[]): IndexedFieldItem[] { const { indexPattern, fieldWildcardMatcher, helpers, userEditPermission } = this.props; const sourceFilters = - indexPattern.sourceFilters && - indexPattern.sourceFilters.map((f: Record) => f.value); + indexPattern.sourceFilters && indexPattern.sourceFilters.map((f) => f.value); const fieldWildcardMatch = fieldWildcardMatcher(sourceFilters || []); return ( @@ -83,10 +82,11 @@ export class IndexedFieldsTable extends Component< getFilteredFields = createSelector( (state: IndexedFieldsTableState) => state.fields, - (state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => props.fieldFilter, - (state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => + (_state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => props.fieldFilter, + (_state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => props.indexedFieldTypeFilter, - (state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => props.schemaFieldTypeFilter, + (_state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => + props.schemaFieldTypeFilter, (fields, fieldFilter, indexedFieldTypeFilter, schemaFieldTypeFilter) => { if (fieldFilter) { const normalizedFieldFilter = fieldFilter.toLowerCase(); diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx index 6030f653f9562..e4671a1fc11cf 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx @@ -73,7 +73,7 @@ export interface TableProps { items: SourceFiltersTableFilter[]; deleteFilter: Function; fieldWildcardMatcher: Function; - saveFilter: (filter: SourceFiltersTableFilter) => any; + saveFilter: (filter: SourceFiltersTableFilter) => void; isSaving: boolean; } @@ -150,7 +150,7 @@ export class Table extends Component { ]); const matches = indexPattern .getNonScriptedFields() - .map((currentFilter: any) => currentFilter.name) + .map((currentFilter) => currentFilter.name) .filter(wildcardMatcher) .sort(); diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx index 3d3d167f732da..455371d6c5e2b 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/source_filters_table.tsx @@ -23,7 +23,7 @@ export interface SourceFiltersTableProps { } export interface SourceFiltersTableState { - filterToDelete: any; + filterToDelete: SourceFiltersTableFilter | undefined; isDeleteConfirmationModalVisible: boolean; isSaving: boolean; filters: SourceFiltersTableFilter[]; @@ -56,7 +56,7 @@ export class SourceFiltersTable extends Component< updateFilters = () => { const sourceFilters = this.props.indexPattern.sourceFilters; - const filters = (sourceFilters || []).map((sourceFilter: any) => ({ + const filters = (sourceFilters || []).map((sourceFilter) => ({ ...sourceFilter, clientId: ++this.clientSideId, })); @@ -66,7 +66,7 @@ export class SourceFiltersTable extends Component< getFilteredFilters = createSelector( (state: SourceFiltersTableState) => state.filters, - (state: SourceFiltersTableState, props: SourceFiltersTableProps) => props.filterFilter, + (_state: SourceFiltersTableState, props: SourceFiltersTableProps) => props.filterFilter, (filters, filterFilter) => { if (filterFilter) { const filterFilterToLowercase = filterFilter.toLowerCase(); @@ -98,7 +98,7 @@ export class SourceFiltersTable extends Component< const { filterToDelete, filters } = this.state; indexPattern.sourceFilters = filters.filter((filter) => { - return filter.clientId !== filterToDelete.clientId; + return filter.clientId !== filterToDelete?.clientId; }); this.setState({ isSaving: true }); diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx index de4e455cd48af..a4b87110521d7 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx @@ -141,7 +141,6 @@ export function Tabs({ saveIndexPattern, fields, history, - location, refreshFields, relationships, allowedTypes, @@ -158,7 +157,10 @@ export function Tabs({ savedObjectsManagement, } = useKibana().services; const [fieldFilter, setFieldFilter] = useState(''); - const [syncingStateFunc, setSyncingStateFunc] = useState({ + const [syncingStateFunc, setSyncingStateFunc] = useState<{ + getCurrentTab: () => string; + setCurrentTab?: (newTab: string) => { tab: string }; + }>({ getCurrentTab: () => TAB_INDEXED_FIELDS, }); const [scriptedFieldLanguageFilter, setScriptedFieldLanguageFilter] = useState([]); @@ -260,7 +262,7 @@ export function Tabs({ }, [closeFieldEditor]); const fieldWildcardMatcherDecorated = useCallback( - (filters: string[]) => fieldWildcardMatcher(filters, uiSettings.get(META_FIELDS)), + (filters: string[] | undefined) => fieldWildcardMatcher(filters, uiSettings.get(META_FIELDS)), [uiSettings] ); @@ -600,7 +602,7 @@ export function Tabs({ selectedTab={euiTabs.find((tab) => tab.id === selectedTabId)} onTabClick={(tab) => { setSelectedTabId(tab.id); - syncingStateFunc.setCurrentTab(tab.id); + syncingStateFunc.setCurrentTab?.(tab.id); }} /> ); diff --git a/src/plugins/data_view_management/public/components/field_editor/components/field_format_editor/field_format_editor.test.tsx b/src/plugins/data_view_management/public/components/field_editor/components/field_format_editor/field_format_editor.test.tsx index 89be237adac58..65cb1749e3459 100644 --- a/src/plugins/data_view_management/public/components/field_editor/components/field_format_editor/field_format_editor.test.tsx +++ b/src/plugins/data_view_management/public/components/field_editor/components/field_format_editor/field_format_editor.test.tsx @@ -6,11 +6,11 @@ * Side Public License, v 1. */ -import React, { PureComponent } from 'react'; +import { FormatEditorServiceStart } from '@kbn/data-view-field-editor-plugin/public/service'; +import type { FieldFormat } from '@kbn/field-formats-plugin/common'; import { shallow } from 'enzyme'; - +import React, { PureComponent } from 'react'; import { FieldFormatEditor } from './field_format_editor'; -import type { FieldFormat } from '@kbn/field-formats-plugin/common'; class TestEditor extends PureComponent { render() { @@ -21,12 +21,11 @@ class TestEditor extends PureComponent { } } -const formatEditors = { - byFormatId: { - ip: TestEditor, - number: TestEditor, - }, - getById: jest.fn(() => () => Promise.resolve(TestEditor)), +const formatEditors: FormatEditorServiceStart['fieldFormatEditors'] = { + getById: jest.fn( + () => () => Promise.resolve(TestEditor) + ) as unknown as FormatEditorServiceStart['fieldFormatEditors']['getById'], + getAll: jest.fn(), }; describe('FieldFormatEditor', () => { diff --git a/src/plugins/data_view_management/public/components/field_editor/components/field_format_editor/field_format_editor.tsx b/src/plugins/data_view_management/public/components/field_editor/components/field_format_editor/field_format_editor.tsx index 0b0018629f02d..fe6ae3158a971 100644 --- a/src/plugins/data_view_management/public/components/field_editor/components/field_format_editor/field_format_editor.tsx +++ b/src/plugins/data_view_management/public/components/field_editor/components/field_format_editor/field_format_editor.tsx @@ -6,32 +6,35 @@ * Side Public License, v 1. */ -import React, { LazyExoticComponent, PureComponent } from 'react'; -import { memoize } from 'lodash'; import { EuiDelayRender, EuiLoadingContent } from '@elastic/eui'; import type { - FieldFormatEditorFactory, FieldFormatEditor as InnerFieldFormatEditor, + FieldFormatEditorFactory, } from '@kbn/data-view-field-editor-plugin/public'; -import type { FieldFormat } from '@kbn/field-formats-plugin/common'; +import { FormatEditorServiceStart } from '@kbn/data-view-field-editor-plugin/public'; +import type { FieldFormat, FieldFormatParams } from '@kbn/field-formats-plugin/common'; +import { memoize } from 'lodash'; +import React, { LazyExoticComponent, PureComponent } from 'react'; export interface FieldFormatEditorProps { fieldType: string; fieldFormat: FieldFormat; fieldFormatId: string; - fieldFormatParams: { [key: string]: unknown }; - fieldFormatEditors: any; - onChange: (change: { [key: string]: any }) => void; + fieldFormatParams: FieldFormatParams<{ type?: string }>; + fieldFormatEditors: FormatEditorServiceStart['fieldFormatEditors']; + onChange: (change: FieldFormatParams) => void; onError: (error?: string) => void; } interface FieldFormatEditorState { - EditorComponent: LazyExoticComponent | null; + EditorComponent: LazyExoticComponent> | null; } // use memoize to get stable reference const unwrapEditor = memoize( - (editorFactory: FieldFormatEditorFactory | null): FieldFormatEditorState['EditorComponent'] => { + ( + editorFactory: FieldFormatEditorFactory | undefined + ): FieldFormatEditorState['EditorComponent'] => { if (!editorFactory) return null; return React.lazy(() => editorFactory().then((editor) => ({ default: editor }))); } diff --git a/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx b/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx index 0eb0898f41b60..76df576033e39 100644 --- a/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx +++ b/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx @@ -105,7 +105,7 @@ export class TestScript extends Component { this.setState({ isLoading: false, - previewData: scriptResponse.hits?.hits.map((hit: any) => ({ + previewData: scriptResponse.hits?.hits.map((hit) => ({ _id: hit._id, ...hit._source, ...hit.fields, diff --git a/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx b/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx index 460d0317b2323..a73f3fee90dda 100644 --- a/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx +++ b/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx @@ -33,10 +33,19 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { PainlessLang } from '@kbn/monaco'; -import type { FieldFormatInstanceType, FieldFormatParams } from '@kbn/field-formats-plugin/common'; +import type { + FieldFormat, + FieldFormatInstanceType, + FieldFormatParams, +} from '@kbn/field-formats-plugin/common'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import { KBN_FIELD_TYPES, ES_FIELD_TYPES } from '@kbn/field-types'; -import { DataView, DataViewField, DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import { + DataView, + DataViewField, + DataViewsPublicPluginStart, + FieldSpec, +} from '@kbn/data-views-plugin/public'; import { context as contextType, CodeEditor } from '@kbn/kibana-react-plugin/public'; import { getEnabledScriptingLanguages, @@ -97,14 +106,14 @@ export interface FieldEditorState { fieldTypeFormats: FieldTypeFormat[]; existingFieldNames: string[]; fieldFormatId?: string; - fieldFormatParams: FieldFormatParams; + fieldFormatParams?: FieldFormatParams; showScriptingHelp: boolean; showDeleteModal: boolean; hasFormatError: boolean; hasScriptError: boolean; isSaving: boolean; errors?: string[]; - format: any; + format: FieldFormat; spec: DataViewField['spec']; customLabel: string; } @@ -196,9 +205,9 @@ export class FieldEditor extends PureComponent { + onFieldChange = (fieldName: keyof FieldSpec, value: string | number) => { const { spec } = this.state; - (spec as any)[fieldName] = value; + (spec[fieldName] as string | number) = value; this.forceUpdate(); }; @@ -227,7 +236,7 @@ export class FieldEditor extends PureComponent { + onFormatChange = (formatId: string, params?: FieldFormatParams) => { const { fieldTypeFormats } = this.state; const { uiSettings, fieldFormats } = this.context.services; @@ -244,7 +253,7 @@ export class FieldEditor extends PureComponent { + onFormatParamsChange = (newParams: FieldFormatParams) => { const { fieldFormatId } = this.state; this.onFormatChange(fieldFormatId as string, newParams); }; diff --git a/src/plugins/data_view_management/public/components/field_editor/types.ts b/src/plugins/data_view_management/public/components/field_editor/types.ts index 440833fa04809..8bce5a9f3c26d 100644 --- a/src/plugins/data_view_management/public/components/field_editor/types.ts +++ b/src/plugins/data_view_management/public/components/field_editor/types.ts @@ -9,6 +9,7 @@ import { ReactText } from 'react'; import { Query } from '@kbn/es-query'; import { HttpStart } from '@kbn/core/public'; +import { estypes } from '@elastic/elasticsearch'; export type SampleInput = ReactText | ReactText[] | Record; export interface Sample { @@ -27,8 +28,8 @@ export interface ExecuteScriptParams { export interface ExecuteScriptResult { status: number; - hits?: { hits: any[] }; - error?: any; + hits?: { hits: Array> }; + error?: unknown; } export type ExecuteScript = (params: ExecuteScriptParams) => Promise; diff --git a/src/plugins/data_views/common/data_views/data_views.ts b/src/plugins/data_views/common/data_views/data_views.ts index a92f18029bd4a..12a06b9a98fa7 100644 --- a/src/plugins/data_views/common/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -33,7 +33,7 @@ import { } from '../types'; import { META_FIELDS, SavedObject } from '..'; import { DataViewMissingIndices } from '../lib'; -import { findByTitle } from '../utils'; +import { findByName } from '../utils'; import { DuplicateDataViewError, DataViewInsufficientAccessError } from '../errors'; const MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS = 3; @@ -772,12 +772,17 @@ export class DataViewsService { * @param skipFetchFields if true, will not fetch fields * @returns DataView */ - async create({ id, ...restOfSpec }: DataViewSpec, skipFetchFields = false): Promise { + async create( + { id, name, title, ...restOfSpec }: DataViewSpec, + skipFetchFields = false + ): Promise { const shortDotsEnable = await this.config.get(FORMATS_UI_SETTINGS.SHORT_DOTS_ENABLE); const metaFields = await this.config.get(META_FIELDS); const spec = { id: id ?? uuid.v4(), + title, + name: name || title, ...restOfSpec, }; @@ -821,12 +826,13 @@ export class DataViewsService { if (!(await this.getCanSave())) { throw new DataViewInsufficientAccessError(); } - const dupe = await findByTitle(this.savedObjectsClient, dataView.title); + const dupe = await findByName(this.savedObjectsClient, dataView.getName()); + if (dupe) { if (override) { await this.delete(dupe.id); } else { - throw new DuplicateDataViewError(`Duplicate data view: ${dataView.title}`); + throw new DuplicateDataViewError(`Duplicate data view: ${dataView.getName()}`); } } diff --git a/src/plugins/data_views/common/utils.ts b/src/plugins/data_views/common/utils.ts index 98f55d6265d27..c12e6c71c92ba 100644 --- a/src/plugins/data_views/common/utils.ts +++ b/src/plugins/data_views/common/utils.ts @@ -12,22 +12,22 @@ import type { SavedObjectsClientCommon } from './types'; import { DATA_VIEW_SAVED_OBJECT_TYPE } from './constants'; /** - * Returns an object matching a given title + * Returns an object matching a given name * * @param client {SavedObjectsClientCommon} - * @param title {string} - * @returns {Promise} + * @param name {string} + * @returns {SavedObject|undefined} */ -export async function findByTitle(client: SavedObjectsClientCommon, title: string) { - if (title) { +export async function findByName(client: SavedObjectsClientCommon, name: string) { + if (name) { const savedObjects = await client.find({ type: DATA_VIEW_SAVED_OBJECT_TYPE, perPage: 10, - search: `"${title}"`, - searchFields: ['title'], - fields: ['title'], + search: `"${name}"`, + searchFields: ['name'], + fields: ['name'], }); - return savedObjects.find((obj) => obj.attributes.title.toLowerCase() === title.toLowerCase()); + return savedObjects ? savedObjects[0] : undefined; } } diff --git a/src/plugins/data_views/public/data_views/data_views_api_client.test.mock.ts b/src/plugins/data_views/public/data_views/data_views_api_client.test.mock.ts index 5880bd9fd36fa..fd12291a2bc16 100644 --- a/src/plugins/data_views/public/data_views/data_views_api_client.test.mock.ts +++ b/src/plugins/data_views/public/data_views/data_views_api_client.test.mock.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { setup } from '@kbn/core/test_helpers/http_test_setup'; +import { setup } from '@kbn/core-test-helpers-http-setup-browser'; export const { http } = setup((injectedMetadata) => { injectedMetadata.getBasePath.mockReturnValue('/hola/daro/'); diff --git a/src/plugins/data_views/server/rest_api_routes/create_data_view.ts b/src/plugins/data_views/server/rest_api_routes/create_data_view.ts index c0b01329f5866..00897c364e085 100644 --- a/src/plugins/data_views/server/rest_api_routes/create_data_view.ts +++ b/src/plugins/data_views/server/rest_api_routes/create_data_view.ts @@ -113,7 +113,7 @@ const registerCreateDataViewRouteFactory = const dataView = await createDataView({ dataViewsService, usageCollection, - spec: spec as DataViewSpec, + spec: { ...spec, name: spec.name || spec.title } as DataViewSpec, override: body.override, refreshFields: body.refresh_fields, counterName: `${req.route.method} ${path}`, diff --git a/src/plugins/data_views/server/routes/fields_for.ts b/src/plugins/data_views/server/routes/fields_for.ts index 3ad854ab0d6ac..60321c7185185 100644 --- a/src/plugins/data_views/server/routes/fields_for.ts +++ b/src/plugins/data_views/server/routes/fields_for.ts @@ -6,15 +6,16 @@ * Side Public License, v 1. */ +import { estypes } from '@elastic/elasticsearch'; import { schema } from '@kbn/config-schema'; import { IRouter, - StartServicesAccessor, RequestHandler, RouteValidatorFullConfig, + StartServicesAccessor, } from '@kbn/core/server'; -import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; import { IndexPatternsFetcher } from '../fetcher'; +import type { DataViewsServerPluginStart, DataViewsServerPluginStartDependencies } from '../types'; const parseMetaFields = (metaFields: string | string[]) => { let parsedFields: string[] = []; @@ -28,7 +29,7 @@ const parseMetaFields = (metaFields: string | string[]) => { const path = '/api/index_patterns/_fields_for_wildcard'; -type IBody = { index_filter?: any } | undefined; +type IBody = { index_filter?: estypes.QueryDslQueryContainer } | undefined; interface IQuery { pattern: string; meta_fields: string[]; diff --git a/src/plugins/data_views/server/saved_objects/data_views.ts b/src/plugins/data_views/server/saved_objects/data_views.ts index 6319911f3bfd5..064302e2b6fe6 100644 --- a/src/plugins/data_views/server/saved_objects/data_views.ts +++ b/src/plugins/data_views/server/saved_objects/data_views.ts @@ -18,10 +18,10 @@ export const dataViewSavedObjectType: SavedObjectsType = { management: { displayName: 'data view', icon: 'indexPatternApp', - defaultSearchField: 'title', + defaultSearchField: 'name', importableAndExportable: true, getTitle(obj) { - return obj.attributes.title; + return obj.attributes.name || obj.attributes.title; }, getEditUrl(obj) { return `/management/kibana/dataViews/dataView/${encodeURIComponent(obj.id)}`; @@ -38,6 +38,7 @@ export const dataViewSavedObjectType: SavedObjectsType = { properties: { title: { type: 'text' }, type: { type: 'keyword' }, + name: { type: 'text' }, }, }, migrations: indexPatternSavedObjectTypeMigrations as any, diff --git a/src/plugins/data_views/server/saved_objects/index_pattern_migrations.ts b/src/plugins/data_views/server/saved_objects/index_pattern_migrations.ts index d92b39e8a6c24..c039e802f69e7 100644 --- a/src/plugins/data_views/server/saved_objects/index_pattern_migrations.ts +++ b/src/plugins/data_views/server/saved_objects/index_pattern_migrations.ts @@ -9,7 +9,10 @@ import { flow, omit } from 'lodash'; import { SavedObjectMigrationFn } from '@kbn/core/server'; -const migrateAttributeTypeAndAttributeTypeMeta: SavedObjectMigrationFn = (doc) => ({ +const migrateAttributeTypeAndAttributeTypeMeta: SavedObjectMigrationFn< + { type?: string; typeMeta?: string }, + unknown +> = (doc) => ({ ...doc, attributes: { ...doc.attributes, @@ -18,11 +21,14 @@ const migrateAttributeTypeAndAttributeTypeMeta: SavedObjectMigrationFn }, }); -const migrateSubTypeAndParentFieldProperties: SavedObjectMigrationFn = (doc) => { +const migrateSubTypeAndParentFieldProperties: SavedObjectMigrationFn< + { fields?: string }, + unknown +> = (doc) => { if (!doc.attributes.fields) return doc; const fieldsString = doc.attributes.fields; - const fields = JSON.parse(fieldsString) as any[]; + const fields = JSON.parse(fieldsString) as Array<{ subType?: string; parent?: string }>; const migratedFields = fields.map((field) => { if (field.subType === 'multi') { return { @@ -43,7 +49,7 @@ const migrateSubTypeAndParentFieldProperties: SavedObjectMigrationFn = }; }; -const addAllowNoIndex: SavedObjectMigrationFn = (doc) => ({ +const addAllowNoIndex: SavedObjectMigrationFn<{}, unknown> = (doc) => ({ ...doc, attributes: { ...doc.attributes, diff --git a/src/plugins/discover/public/application/context/context_app.test.tsx b/src/plugins/discover/public/application/context/context_app.test.tsx index 828ec0d0eeb1a..032e815690d70 100644 --- a/src/plugins/discover/public/application/context/context_app.test.tsx +++ b/src/plugins/discover/public/application/context/context_app.test.tsx @@ -21,6 +21,7 @@ import { uiSettingsMock } from '../../__mocks__/ui_settings'; import { themeServiceMock } from '@kbn/core/public/mocks'; import { LocalStorageMock } from '../../__mocks__/local_storage_mock'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; const mockFilterManager = createFilterManagerMock(); const mockNavigationPlugin = { ui: { TopNavMenu: mockTopNavMenu } }; @@ -28,6 +29,7 @@ const mockNavigationPlugin = { ui: { TopNavMenu: mockTopNavMenu } }; describe('ContextApp test', () => { const services = { data: { + ...dataPluginMock.createStartContract(), search: { searchSource: { createEmpty: jest.fn(), diff --git a/src/plugins/discover/public/application/context/context_app.tsx b/src/plugins/discover/public/application/context/context_app.tsx index ee7203e3c780c..74f5910a4dec3 100644 --- a/src/plugins/discover/public/application/context/context_app.tsx +++ b/src/plugins/discover/public/application/context/context_app.tsx @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import { DOC_TABLE_LEGACY, SEARCH_FIELDS_FROM_SOURCE } from '../../../common'; import { ContextErrorMessage } from './components/context_error_message'; import { LoadingStatus } from './services/context_query_state'; -import { AppState, isEqualFilters } from './services/context_state'; +import { AppState, GlobalState, isEqualFilters } from './services/context_state'; import { useColumns } from '../../hooks/use_data_grid_columns'; import { useContextAppState } from './hooks/use_context_app_state'; import { useContextAppFetch } from './hooks/use_context_app_fetch'; @@ -52,8 +52,9 @@ export const ContextApp = ({ indexPattern, anchorId }: ContextAppProps) => { /** * Context app state */ - const { appState, setAppState } = useContextAppState({ services }); + const { appState, globalState, setAppState } = useContextAppState({ services }); const prevAppState = useRef(); + const prevGlobalState = useRef({ filters: [] }); /** * Context fetched state @@ -85,13 +86,18 @@ export const ContextApp = ({ indexPattern, anchorId }: ContextAppProps) => { fetchSurroundingRows(SurrDocType.PREDECESSORS); } else if (prevAppState.current.successorCount !== appState.successorCount) { fetchSurroundingRows(SurrDocType.SUCCESSORS); - } else if (!isEqualFilters(prevAppState.current.filters, appState.filters)) { + } else if ( + !isEqualFilters(prevAppState.current.filters, appState.filters) || + !isEqualFilters(prevGlobalState.current.filters, globalState.filters) + ) { fetchContextRows(); } prevAppState.current = cloneDeep(appState); + prevGlobalState.current = cloneDeep(globalState); }, [ appState, + globalState, anchorId, fetchContextRows, fetchAllRows, diff --git a/src/plugins/discover/public/application/context/hooks/use_context_app_fetch.tsx b/src/plugins/discover/public/application/context/hooks/use_context_app_fetch.tsx index 1201526da0821..ee6773507b932 100644 --- a/src/plugins/discover/public/application/context/hooks/use_context_app_fetch.tsx +++ b/src/plugins/discover/public/application/context/hooks/use_context_app_fetch.tsx @@ -130,17 +130,19 @@ export function useContextAppFetch({ try { setState({ [statusKey]: { value: LoadingStatus.LOADING } }); - const rows = await fetchSurroundingDocs( - type, - indexPattern, - anchor, - tieBreakerField, - SortDirection.desc, - count, - filters, - data, - useNewFieldsApi - ); + const rows = anchor.id + ? await fetchSurroundingDocs( + type, + indexPattern, + anchor, + tieBreakerField, + SortDirection.desc, + count, + filters, + data, + useNewFieldsApi + ) + : []; setState({ [type]: rows, [statusKey]: { value: LoadingStatus.LOADED } }); } catch (error) { setState(createError(statusKey, FailureReason.UNKNOWN, error)); diff --git a/src/plugins/discover/public/application/context/hooks/use_context_app_state.ts b/src/plugins/discover/public/application/context/hooks/use_context_app_state.ts index 9accdb363af92..594ef3d3ffd4c 100644 --- a/src/plugins/discover/public/application/context/hooks/use_context_app_state.ts +++ b/src/plugins/discover/public/application/context/hooks/use_context_app_state.ts @@ -7,13 +7,12 @@ */ import { useEffect, useMemo, useState } from 'react'; -import { cloneDeep } from 'lodash'; import { CONTEXT_DEFAULT_SIZE_SETTING } from '../../../../common'; import { DiscoverServices } from '../../../build_services'; -import { AppState, getState } from '../services/context_state'; +import { AppState, getState, GlobalState } from '../services/context_state'; export function useContextAppState({ services }: { services: DiscoverServices }) { - const { uiSettings: config, history, core, filterManager } = services; + const { uiSettings: config, history, core } = services; const stateContainer = useMemo(() => { return getState({ @@ -22,10 +21,14 @@ export function useContextAppState({ services }: { services: DiscoverServices }) history: history(), toasts: core.notifications.toasts, uiSettings: config, + data: services.data, }); - }, [config, history, core.notifications.toasts]); + }, [config, history, core.notifications.toasts, services.data]); - const [appState, setState] = useState(stateContainer.appState.getState()); + const [appState, setAppState] = useState(stateContainer.appState.getState()); + const [globalState, setGlobalState] = useState( + stateContainer.globalState.getState() + ); /** * Sync with app state container @@ -38,32 +41,24 @@ export function useContextAppState({ services }: { services: DiscoverServices }) useEffect(() => { const unsubscribeAppState = stateContainer.appState.subscribe((newState) => { - setState((prevState) => ({ ...prevState, ...newState })); + const newStateEnsureFilter = { ...newState, filters: newState.filters ?? [] }; + setAppState((prevState) => ({ ...prevState, ...newStateEnsureFilter })); }); - return () => unsubscribeAppState(); - }, [stateContainer, setState]); - - /** - * Take care of filters - */ - useEffect(() => { - const filters = stateContainer.appState.getState().filters; - if (filters) { - filterManager.setAppFilters(cloneDeep(filters)); - } - - const { setFilters } = stateContainer; - const filterObservable = filterManager.getUpdates$().subscribe(() => { - setFilters(filterManager); + const unsubscribeGlobalState = stateContainer.globalState.subscribe((newState) => { + const newStateEnsureFilter = { ...newState, filters: newState.filters ?? [] }; + setGlobalState((prevState) => ({ ...prevState, ...newStateEnsureFilter })); }); - return () => filterObservable.unsubscribe(); - }, [filterManager, stateContainer]); + return () => { + unsubscribeAppState(); + unsubscribeGlobalState(); + }; + }, [stateContainer, setAppState]); return { appState, - stateContainer, + globalState, setAppState: stateContainer.setAppState, }; } diff --git a/src/plugins/discover/public/application/context/services/context_state.test.ts b/src/plugins/discover/public/application/context/services/context_state.test.ts index 4e64ff206647e..a420b8d08e0b6 100644 --- a/src/plugins/discover/public/application/context/services/context_state.test.ts +++ b/src/plugins/discover/public/application/context/services/context_state.test.ts @@ -13,7 +13,10 @@ import { createBrowserHistory, History } from 'history'; import { FilterManager } from '@kbn/data-plugin/public'; import { coreMock } from '@kbn/core/public/mocks'; import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../common'; +import { discoverServiceMock } from '../../../__mocks__/services'; +discoverServiceMock.data.query.filterManager.getAppFilters = jest.fn(() => []); +discoverServiceMock.data.query.filterManager.getGlobalFilters = jest.fn(() => []); const setupMock = coreMock.createSetup(); describe('Test Discover Context State', () => { @@ -30,6 +33,7 @@ describe('Test Discover Context State', () => { get: (key: string) => (key === SEARCH_FIELDS_FROM_SOURCE ? true : ['_source']) as unknown as T, } as IUiSettingsClient, + data: discoverServiceMock.data, }); state.startSync(); }); @@ -47,7 +51,11 @@ describe('Test Discover Context State', () => { "successorCount": 4, } `); - expect(state.globalState.getState()).toMatchInlineSnapshot(`null`); + expect(state.globalState.getState()).toMatchInlineSnapshot(` + Object { + "filters": Array [], + } + `); expect(state.startSync).toBeDefined(); expect(state.stopSync).toBeDefined(); expect(state.getFilters()).toStrictEqual([]); diff --git a/src/plugins/discover/public/application/context/services/context_state.ts b/src/plugins/discover/public/application/context/services/context_state.ts index 77fa33faa14c8..9739b5bc0fde4 100644 --- a/src/plugins/discover/public/application/context/services/context_state.ts +++ b/src/plugins/discover/public/application/context/services/context_state.ts @@ -6,10 +6,10 @@ * Side Public License, v 1. */ -import { isEqual } from 'lodash'; +import { cloneDeep, isEqual } from 'lodash'; import { History } from 'history'; import { NotificationsStart, IUiSettingsClient } from '@kbn/core/public'; -import { Filter, compareFilters, COMPARE_ALL_OPTIONS } from '@kbn/es-query'; +import { Filter, compareFilters, COMPARE_ALL_OPTIONS, FilterStateStore } from '@kbn/es-query'; import { createStateContainer, createKbnUrlStateStorage, @@ -18,7 +18,7 @@ import { ReduxLikeStateContainer, } from '@kbn/kibana-utils-plugin/public'; -import { FilterManager } from '@kbn/data-plugin/public'; +import { connectToQueryState, DataPublicPluginStart, FilterManager } from '@kbn/data-plugin/public'; import { handleSourceColumnState } from '../../../utils/state_helpers'; export interface AppState { @@ -46,7 +46,7 @@ export interface AppState { sort?: string[][]; } -interface GlobalState { +export interface GlobalState { /** * Array of filters */ @@ -78,6 +78,11 @@ export interface GetStateParams { * core ui settings service */ uiSettings: IUiSettingsClient; + + /** + * data service + */ + data: DataPublicPluginStart; } export interface GetStateReturn { @@ -128,6 +133,7 @@ export function getState({ history, toasts, uiSettings, + data, }: GetStateParams): GetStateReturn { const stateStorage = createKbnUrlStateStorage({ useHash: storeInSessionStorage, @@ -135,14 +141,20 @@ export function getState({ ...(toasts && withNotifyOnErrors(toasts)), }); - const globalStateInitial = stateStorage.get(GLOBAL_STATE_URL_KEY) as GlobalState; + const globalStateFromUrl = stateStorage.get(GLOBAL_STATE_URL_KEY) as GlobalState; + const globalStateInitial = createInitialGlobalState(globalStateFromUrl); const globalStateContainer = createStateContainer(globalStateInitial); const appStateFromUrl = stateStorage.get(APP_STATE_URL_KEY) as AppState; const appStateInitial = createInitialAppState(defaultSize, appStateFromUrl, uiSettings); const appStateContainer = createStateContainer(appStateInitial); - const { start, stop } = syncStates([ + const getAllFilters = () => [ + ...getFilters(globalStateContainer.getState()), + ...getFilters(appStateContainer.getState()), + ]; + + const { start: startSyncingStates, stop: stopSyncingStates } = syncStates([ { storageKey: GLOBAL_STATE_URL_KEY, stateContainer: { @@ -173,11 +185,33 @@ export function getState({ }, ]); + let stopSyncingFilters = () => {}; + return { globalState: globalStateContainer, appState: appStateContainer, - startSync: start, - stopSync: stop, + startSync: () => { + data.query.filterManager.setFilters(cloneDeep(getAllFilters())); + + const stopSyncingAppFilters = connectToQueryState(data.query, appStateContainer, { + filters: FilterStateStore.APP_STATE, + }); + const stopSyncingGlobalFilters = connectToQueryState(data.query, globalStateContainer, { + filters: FilterStateStore.GLOBAL_STATE, + }); + + stopSyncingFilters = () => { + stopSyncingAppFilters(); + stopSyncingGlobalFilters(); + }; + + startSyncingStates(); + }, + stopSync: () => { + stopSyncingFilters(); + stopSyncingFilters = () => {}; + stopSyncingStates(); + }, setAppState: (newState: Partial) => { const oldState = appStateContainer.getState(); const mergedState = { ...oldState, ...newState }; @@ -186,10 +220,7 @@ export function getState({ stateStorage.set(APP_STATE_URL_KEY, mergedState, { replace: true }); } }, - getFilters: () => [ - ...getFilters(globalStateContainer.getState()), - ...getFilters(appStateContainer.getState()), - ], + getFilters: getAllFilters, setFilters: (filterManager: FilterManager) => { // global state filters const globalFilters = filterManager.getGlobalFilters(); @@ -282,3 +313,21 @@ function createInitialAppState( uiSettings ); } + +/** + * Helper function to return the initial global state, which is a merged object of url state and + * default state + */ +function createInitialGlobalState(urlState: GlobalState): GlobalState { + const defaultState: GlobalState = { + filters: [], + }; + if (typeof urlState !== 'object') { + return defaultState; + } + + return { + ...defaultState, + ...urlState, + }; +} diff --git a/src/plugins/discover/public/hooks/use_navigation_props.tsx b/src/plugins/discover/public/hooks/use_navigation_props.tsx index 56720776b1553..a62df3f09e2fe 100644 --- a/src/plugins/discover/public/hooks/use_navigation_props.tsx +++ b/src/plugins/discover/public/hooks/use_navigation_props.tsx @@ -66,7 +66,14 @@ const getCurrentBreadcrumbs = ( export const useMainRouteBreadcrumb = () => { // useRef needed to retrieve initial breadcrumb link from the push state without updates - return useRef(useHistory().location.state?.breadcrumb).current; + const breadcrumb = useRef(); + const history = useHistory(); + + if (history.location.state?.breadcrumb) { + breadcrumb.current = history.location.state.breadcrumb; + } + + return breadcrumb.current; }; export const useNavigationProps = ({ diff --git a/src/plugins/es_ui_shared/.storybook/main.ts b/src/plugins/es_ui_shared/.storybook/main.ts new file mode 100644 index 0000000000000..1261fe5a06f69 --- /dev/null +++ b/src/plugins/es_ui_shared/.storybook/main.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. + */ + +import { defaultConfig } from '@kbn/storybook'; + +module.exports = defaultConfig; diff --git a/src/plugins/es_ui_shared/.storybook/manager.ts b/src/plugins/es_ui_shared/.storybook/manager.ts new file mode 100644 index 0000000000000..b5b23ce4099c8 --- /dev/null +++ b/src/plugins/es_ui_shared/.storybook/manager.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { addons } from '@storybook/addons'; +import { create } from '@storybook/theming'; +import { PANEL_ID } from '@storybook/addon-actions'; + +addons.setConfig({ + theme: create({ + base: 'light', + brandTitle: 'Platform Deployment Management Storybook', + brandUrl: 'https://github.com/elastic/kibana/tree/main/src/plugins/es_ui_shared', + }), + showPanel: () => true, + selectedPanel: PANEL_ID, +}); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/constants.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/constants.ts new file mode 100644 index 0000000000000..c1bbc5c7d836f --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/constants.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FieldConfig } from '../../types'; + +/** + * The "title" field base configuration + */ +export const titleConfigBase: FieldConfig = { + label: 'Title', + helpText: 'This is a help text for the field.', +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_de_serializer.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_de_serializer.tsx new file mode 100644 index 0000000000000..9b5cff6b59be4 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_de_serializer.tsx @@ -0,0 +1,175 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { EuiButton } from '@elastic/eui'; + +import { fieldFormatters } from '../../../helpers'; +import { TextField, NumericField } from '../../../components'; +import { useForm } from '../../hooks/use_form'; +import { Form } from '../form'; +import { UseField } from '../use_field'; +import { FormArgs } from './types'; +import { submitForm } from './form_utils'; + +interface MyForm { + endPoint: string; +} + +interface MyFormInternal { + protocol: string; + hostname: string; + port?: number; + pathname: string; +} + +const deserializer = (formDefault: MyForm): MyFormInternal => { + try { + const url = new URL(formDefault.endPoint); + const { protocol, hostname, pathname, port } = url; + + return { + protocol, + hostname, + pathname, + port: parseInt(port, 10), + }; + } catch (e) { + // Invalid URL + return { + protocol: '', + hostname: '', + pathname: '', + }; + } +}; + +const serializer = ({ protocol, hostname, port, pathname }: MyFormInternal): MyForm => ({ + endPoint: `${protocol}//${hostname}:${port}${pathname === '/' ? '' : pathname}`, +}); + +type Args = FormArgs & { endPoint: string }; + +const FormWithDeSerializer = ({ endPoint, ...args }: Args) => { + const { form } = useForm({ + serializer, + deserializer, + defaultValue: { + endPoint, + }, + }); + + return ( +

+ path="protocol" component={TextField} config={{ label: 'Protocol' }} /> + path="hostname" component={TextField} config={{ label: 'Host' }} /> + + path="port" + component={NumericField} + config={{ label: 'Port', formatters: [fieldFormatters.toInt] }} + /> + path="pathname" component={TextField} config={{ label: 'Pathname' }} /> + submitForm(form)}>Send + + ); +}; + +export const DeSerializer = (args: Args) => { + // We add a "key" to force a refresh of the form each time the end point arg changes + return ; +}; + +DeSerializer.storyName = '(De)serializer'; + +DeSerializer.argTypes = { + endPoint: { + name: 'formDefaultValue.endPoint', + description: + 'This endpoint comes from the backend and is passed to the form. We want to split the URL and the port to let the user modify them separately. For that we will deserialize the field into 2 form fields. When sending the form we will serialize back the 2 fields into one.', + defaultValue: 'https://elastic.co:9200', + control: { + type: 'text', + }, + }, +}; + +DeSerializer.parameters = { + docs: { + source: { + code: ` +interface MyForm { + endPoint: string; +} + +interface MyFormInternal { + protocol: string; + hostname: string; + port?: number; + pathname: string; +} + +const deserializer = (formDefault: MyForm): MyFormInternal => { + try { + const url = new URL(formDefault.endPoint); + const { protocol, hostname, pathname, port } = url; + + return { + protocol, + hostname, + pathname, + port: parseInt(port, 10), + }; + } catch (e) { + // Invalid URL + return { + protocol: '', + hostname: '', + pathname: '', + }; + } +}; + +const serializer = ({ protocol, hostname, port, pathname }: MyFormInternal): MyForm => ({ + endPoint: \`\${protocol}//\${hostname}:\${port}\${pathname === '/' ? '' : pathname}\`, +}); + +const MyFormComponent = ({ endPoint }) => { + const { form } = useForm({ + serializer, + deserializer, + defaultValue: { + endPoint, + }, + }); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ path="protocol" component={TextField} config={{ label: 'Protocol' }} /> + path="hostname" component={TextField} config={{ label: 'Host' }} /> + + path="port" + component={NumericField} + config={{ label: 'Port', formatters: [fieldFormatters.toInt] }} + /> + path="pathname" component={TextField} config={{ label: 'Pathname' }} /> + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_default_value.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_default_value.tsx new file mode 100644 index 0000000000000..9946ee7fc30db --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_default_value.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { EuiButton } from '@elastic/eui'; + +import { TextField } from '../../../components'; +import { useForm } from '../../hooks/use_form'; +import { Form } from '../form'; +import { UseField } from '../use_field'; +import { titleConfigBase } from './constants'; +import { FormArgs } from './types'; +import { submitForm } from './form_utils'; + +// The defaultValue would probably come from an HTTP request +const formDefaultValue = { title: 'Title of the post' }; + +export const DefaultValue = (args: FormArgs) => { + const { form } = useForm({ defaultValue: formDefaultValue }); + + return ( +
+ path="title" component={TextField} config={{ ...titleConfigBase }} /> + submitForm(form)}>Send + + ); +}; + +DefaultValue.parameters = { + docs: { + source: { + code: ` +// The defaultValue would probably come from an HTTP request +const formDefaultValue = { title: 'Title of the post' }; + +const MyFormComponent = () => { + const { form } = useForm({ defaultValue: formDefaultValue }); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ path="title" component={TextField} config={{ ...titleConfigBase }} /> + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_global_fields.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_global_fields.tsx new file mode 100644 index 0000000000000..1f5a249bb1465 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_global_fields.tsx @@ -0,0 +1,266 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import React, { useState, useContext, createContext } from 'react'; +import { EuiSpacer, EuiText, EuiTextColor, EuiButton } from '@elastic/eui'; + +import { TextField, NumericField } from '../../../components'; +import { FieldHook } from '../../types'; +import { useForm } from '../../hooks'; +import { Form } from '../form'; +import { UseMultiFields } from '../use_multi_fields'; +import { submitForm } from './form_utils'; + +// map of field ids to "" props +const globalFields = { + fieldA: { + path: 'fieldA', + defaultValue: 'foo', + config: { + label: 'Field A', + }, + }, + fieldB: { + path: 'fieldB', + defaultValue: 123, + config: { + label: 'Field B', + }, + }, +}; + +const FormGlobalFieldsContext = createContext( + {} as { + fieldA: FieldHook; + fieldB: FieldHook; + } +); + +const useGlobalFields = () => { + const ctx = useContext(FormGlobalFieldsContext); + if (!ctx) { + throw new Error('Missing provider'); + } + return ctx; +}; + +const FormGlobalFields: React.FC = ({ children }) => { + return ( + + {(fields) => { + return ( + + {children} + + ); + }} + + ); +}; + +const FormFields = () => { + const { fieldA, fieldB } = useGlobalFields(); + + return ( + <> + } /> + } /> + + ); +}; + +export function GlobalFields() { + const { form } = useForm(); + const [areFieldsVisible, setAreFieldsVisible] = useState(true); + const [areGlobalPresent, setAreGlobalPresent] = useState(true); + + return ( +
+ {areGlobalPresent && ( + + +

+ + You might need to have global fields in you form that persist their value event when + a field unmounts. The recommended pattern is to use a React context along with + "UseMultiFields" + +

+
+ + + + {areFieldsVisible && } + + setAreFieldsVisible((prev) => !prev)}> + Toggle fields in DOM + + +

+ + Removing fields from DOM (that are connected to globals) will still preserve their + value in the form. + +

+
+
+ )} +
+ + setAreGlobalPresent((prev) => !prev)}> + Toggle globals fields + + +

+ + Removing the global fields from DOM remove their value when sending the form. + +

+
+
+ +
+ + submitForm(form)}>Send form +
+
+ ); +} + +GlobalFields.storyName = 'GlobalFields'; + +GlobalFields.parameters = { + docs: { + source: { + code: ` +// map of field ids to "" props +const globalFields = { + fieldA: { + path: 'fieldA', + defaultValue: 'foo', + config: { + label: 'Field A', + }, + }, + fieldB: { + path: 'fieldB', + defaultValue: 123, + config: { + label: 'Field B', + }, + }, +}; + +const FormGlobalFieldsContext = createContext( + {} as { + fieldA: FieldHook; + fieldB: FieldHook; + } +); + +const useGlobalFields = () => { + const ctx = useContext(FormGlobalFieldsContext); + if (!ctx) { + throw new Error('Missing provider'); + } + return ctx; +}; + +const FormGlobalFields: React.FC = ({ children }) => { + return ( + + {(fields) => { + return ( + + {children} + + ); + }} + + ); +}; + +const FormFields = () => { + const { fieldA, fieldB } = useGlobalFields(); + + return ( + <> + + + + ); +}; + +const MyFormComponent = () => { + const { form } = useForm(); + const [areFieldsVisible, setAreFieldsVisible] = useState(true); + const [areGlobalPresent, setAreGlobalPresent] = useState(true); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ {areGlobalPresent && ( + + +

+ + You might need to have global fields in you form that persist their value event when + a field unmounts. The recommended pattern is to use a React context along with + "UseMultiFields" + +

+
+ + + + {areFieldsVisible && } + + setAreFieldsVisible((prev) => !prev)}> + Toggle fields in DOM + + +

+ + Removing fields from DOM (that are connected to globals) will still preserve their + value in the form. + +

+
+
+ )} +
+ + setAreGlobalPresent((prev) => !prev)}> + Toggle globals fields + + +

+ + Removing the global fields from DOM remove their value when sending the form. + +

+
+
+ +
+ + Send form +
+
+ ); +}; + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_is_modified.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_is_modified.tsx new file mode 100644 index 0000000000000..8dc112909e656 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_is_modified.tsx @@ -0,0 +1,90 @@ +/* + * Copyright 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 } from 'react'; +import { EuiButton } from '@elastic/eui'; +import { action } from '@storybook/addon-actions'; + +import { TextField, ToggleField } from '../../../components'; +import { useForm } from '../../hooks/use_form'; +import { useFormIsModified } from '../../hooks/use_form_is_modified'; +import { Form } from '../form'; +import { UseField } from '../use_field'; +import { titleConfigBase } from './constants'; +import { FormArgs } from './types'; +import { submitForm } from './form_utils'; + +export const IsModified = (args: FormArgs) => { + const { form } = useForm(); + const isFormModified = useFormIsModified({ form }); + + useEffect(() => { + action('Is form modified')(isFormModified); + }, [isFormModified]); + + return ( +
+ + path="title" + defaultValue="Initial value" + component={TextField} + config={titleConfigBase} + /> + + path="isOn" + defaultValue={true} + component={ToggleField} + config={{ label: 'Is on' }} + /> + submitForm(form)}>Send + + ); +}; + +IsModified.parameters = { + docs: { + source: { + code: ` +const MyFormComponent = () => { + const { form } = useForm(); + const isFormModified = useFormIsModified({ form }); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + useEffect(() => { + // Do something whenever the form is modified + }, [isFormModified]); + + return ( +
+ + path="title" + defaultValue="Initial value" + component={TextField} + config={titleConfigBase} + /> + + path="isOn" + defaultValue={true} + component={ToggleField} + config={{ label: 'Is on' }} + /> + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_utils.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_utils.tsx new file mode 100644 index 0000000000000..e72f7600031c7 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_utils.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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, { FC } from 'react'; +import { EuiSpacer, EuiButton } from '@elastic/eui'; +import { action } from '@storybook/addon-actions'; + +import { useForm } from '../../hooks/use_form'; +import { FormHook, FormConfig } from '../../types'; +import { Form } from '../form'; + +/** + * Validate the form and return its data. + * + * @param form The FormHook instance + */ +export const submitForm = async (form: FormHook) => { + const { isValid, data } = await form.submit(); + action('Send form')({ + isValid, + data: JSON.stringify(data), + }); +}; + +export interface FormWrapperProps { + formConfig?: FormConfig; +} + +export const FormWrapper: FC = ({ formConfig, children }) => { + const { form } = useForm(formConfig); + + return ( +
+ <> + {children} + + submitForm(form)}>Send + + + ); +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_validation.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_validation.tsx new file mode 100644 index 0000000000000..58ca24fe0ffed --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/form_validation.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { EuiButton } from '@elastic/eui'; +import { action } from '@storybook/addon-actions'; + +import { TextField } from '../../../components'; +import { FieldConfig } from '../../types'; +import { useForm } from '../../hooks/use_form'; +import { Form } from '../form'; +import { UseField } from '../use_field'; +import { titleConfigBase } from './constants'; +import { FormArgs } from './types'; +import { submitForm } from './form_utils'; + +const titleConfigWithValidation: FieldConfig = { + ...titleConfigBase, + helpText: 'Test validation by leaving field empty.', + validations: [ + { + validator: ({ value }) => { + action('Validating title field')(value); + + if (value.trim() === '') { + return { + message: `The field can't be empty.`, + }; + } + }, + }, + ], +}; + +export const Validation = (args: FormArgs) => { + const { form } = useForm(); + + return ( +
+ path="title" component={TextField} config={titleConfigWithValidation} /> + submitForm(form)}>Send + + ); +}; + +Validation.parameters = { + docs: { + source: { + code: ` +const titleConfigWithValidation: FieldConfig = { + label: 'Title', + helpText: 'Test validation by leaving field empty.', + validations: [ + { + validator: ({ value }) => { + action('Validating title field')(value); + + if (value.trim() === '') { + return { + message: "The field can't be empty.", + }; + } + }, + }, + ], +}; + +const MyFormComponent = () => { + const { form } = useForm(); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ path="title" component={TextField} config={titleConfigWithValidation} /> + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/index.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/index.ts new file mode 100644 index 0000000000000..945bd9019fd11 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/index.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Validation } from './form_validation'; +import { DeSerializer } from './form_de_serializer'; +import { DefaultValue } from './form_default_value'; +import { IsModified } from './form_is_modified'; +import { GlobalFields } from './form_global_fields'; + +import { submitForm, FormWrapper } from './form_utils'; + +import { FieldTypes as UseFieldFieldTypes } from './use_field_field_types'; +import { ChangeListeners as UseFieldChangeListeners } from './use_field_change_listeners'; + +import { Basic as UseArrayBasic } from './use_array_basic'; +import { Reorder as UseArrayReorder } from './use_array_reorder'; +import { Complex as UseArrayComplex } from './use_array_complex'; +import { DynamicData as UseArrayDynamicData } from './use_array_dynamic_data'; + +import { Basic as UseMultiFieldBasic } from './use_multi_field_basic'; + +export const formStories = { + Validation, + DeSerializer, + DefaultValue, + IsModified, + GlobalFields, +}; + +export const useFieldStories = { + UseFieldFieldTypes, + UseFieldChangeListeners, +}; + +export const useArrayStories = { + UseArrayBasic, + UseArrayReorder, + UseArrayComplex, + UseArrayDynamicData, +}; + +export const useMultiFieldStories = { + UseMultiFieldBasic, +}; + +export const helpers = { + submitForm, +}; + +export { FormWrapper }; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/types.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/types.ts new file mode 100644 index 0000000000000..a8a49626974b9 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/types.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. + */ + +import { Props as FormProps } from '../form'; + +export type FormArgs = Pick; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_basic.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_basic.tsx new file mode 100644 index 0000000000000..1c6b6d55ad7c8 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_basic.tsx @@ -0,0 +1,187 @@ +/* + * Copyright 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 { + EuiFlexGroup, + EuiFlexItem, + EuiButtonIcon, + EuiButtonEmpty, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; + +import { TextField } from '../../../components'; +import { fieldValidators } from '../../../helpers'; +import { FormConfig } from '../../types'; +import { UseField } from '../use_field'; +import { UseArray } from '../use_array'; +import { FormWrapper } from './form_utils'; + +const { emptyField } = fieldValidators; + +const defaultValue = { + employees: [ + { + name: 'John', + lastName: 'Snow', + }, + ], +}; + +const formConfig: FormConfig = { + defaultValue, +}; + +export function Basic() { + return ( + + <> + +

Employees

+
+ + + {({ items, addItem, removeItem }) => { + return ( + <> + {items.map(({ id, path }) => { + return ( + + + + + + + + {items.length > 1 && ( + + removeItem(id)} + aria-label="Remove item" + /> + + )} + + ); + })} + + + Add employee + + + ); + }} + + +
+ ); +} + +Basic.storyName = 'Basic'; + +Basic.parameters = { + docs: { + source: { + code: ` +const defaultValue = { + employees: [ + { + name: 'John', + lastName: 'Snow', + }, + ], +}; + +const MyFormComponent = () => { + const { form } = useForm({ defaultValue }); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ +

Employees

+
+ + + {({ items, addItem, removeItem }) => { + return ( + <> + {items.map(({ id, path }) => { + return ( + + + + + + + + {items.length > 1 && ( + + removeItem(id)} + aria-label="Remove item" + /> + + )} + + ); + })} + + + Add employee + + + ); + }} + + + Send + + ); +} + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_complex.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_complex.tsx new file mode 100644 index 0000000000000..312a085efba55 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_complex.tsx @@ -0,0 +1,543 @@ +/* + * Copyright 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, { FC } from 'react'; +import { get } from 'lodash'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiButtonIcon, + EuiButtonEmpty, + EuiSpacer, + EuiTitle, + EuiHealth, +} from '@elastic/eui'; + +import { TextField, SelectField, SuperSelectField } from '../../../components'; +import { fieldValidators } from '../../../helpers'; +import { useFormData } from '../../hooks'; +import { FormConfig } from '../../types'; +import { UseField } from '../use_field'; +import { UseArray } from '../use_array'; +import { FormWrapper } from './form_utils'; + +const { emptyField } = fieldValidators; + +const typeOptions = [ + { value: 'type_one', text: 'Type one' }, + { value: 'type_two', text: 'Type two' }, +]; + +const processorTypeOptions = [ + { value: 'percentage', text: 'Percentage' }, + { value: 'value', text: 'Value' }, +]; + +const percentageOptions = [ + { + value: 'percentage_config_1', + inputDisplay: ( + + Percentage 1 + + ), + }, + { + value: 'percentage_config_2', + inputDisplay: ( + + Percentage 2 + + ), + }, + { + value: 'percentage_config_3', + inputDisplay: ( + + Percentage 3 + + ), + }, +]; + +const valueOptions = [ + { + value: 'value_config_1', + inputDisplay: ( + + Value 1 + + ), + }, + { + value: 'value_config_2', + inputDisplay: ( + + Value 2 + + ), + }, + { + value: 'value_config_3', + inputDisplay: ( + + Value 3 + + ), + }, +]; + +const configSelect = { label: 'Config' }; + +const PercentageConfigSelect = ({ path }: { path: string }) => { + return ( + + ); +}; + +const ValueConfigSelect = ({ path }: { path: string }) => { + return ( + + ); +}; + +const percentageProcessorTypeConfig = { label: 'Processor type', defaultValue: 'percentage' }; + +const ProcessorTypeConfigurator = ({ basePath }: { basePath: string }) => { + const processorTypePath = `${basePath}.type`; + const processorConfigPath = `${basePath}.config`; + const [formData] = useFormData({ watch: processorTypePath }); + const processorType = get(formData, processorTypePath); + + const renderSelect = () => { + if (!processorType) { + return null; + } + + return processorType === 'percentage' ? ( + + ) : ( + + ); + }; + + return ( + + + + + {renderSelect()} + + ); +}; + +const ProcessorsConfigurator: FC<{ ruleType: string }> = ({ ruleType }) => { + return ( + + {({ items, addItem, removeItem }) => { + return ( + <> + {items.map(({ id, path }) => { + return ( + + + {/* Processor name */} + + + + {/* Processor type & config */} + + + {items.length > 1 && ( + + removeItem(id)} + aria-label="Remove processor" + /> + + )} + + ); + })} + + + {/* Add processor button */} + + Add processor + + + ); + }} + + ); +}; + +const FormContent: FC = () => { + const [{ ruleType }] = useFormData({ watch: 'ruleType' }); + + return ( + <> + +

Rule configurator

+
+ + + {/* Rule type */} + + + + +

Processors

+
+ + {ruleType !== undefined && } + + ); +}; + +const defaultValue = { + ruleType: 'type_one', + processors_type_one: [ + { name: 'Processor 1 name', type: 'value', config: 'value_config_3' }, + { name: 'Processor 2 name', type: 'percentage', config: 'percentage_config_2' }, + ], +}; + +const schema = { + ruleType: { + label: 'Rule type', + defaultValue: 'type_one', + }, +}; + +const formConfig: FormConfig = { + schema, + defaultValue, +}; + +export function Complex() { + return ( + + + + ); +} + +Complex.storyName = 'Complex'; + +Complex.parameters = { + docs: { + source: { + code: ` +const typeOptions = [ + { value: 'type_one', text: 'Type one' }, + { value: 'type_two', text: 'Type two' }, +]; + +const processorTypeOptions = [ + { value: 'percentage', text: 'Percentage' }, + { value: 'value', text: 'Value' }, +]; + +const percentageOptions = [ + { + value: 'percentage_config_1', + inputDisplay: ( + + Percentage 1 + + ), + }, + { + value: 'percentage_config_2', + inputDisplay: ( + + Percentage 2 + + ), + }, + { + value: 'percentage_config_3', + inputDisplay: ( + + Percentage 3 + + ), + }, +]; + +const valueOptions = [ + { + value: 'value_config_1', + inputDisplay: ( + + Value 1 + + ), + }, + { + value: 'value_config_2', + inputDisplay: ( + + Value 2 + + ), + }, + { + value: 'value_config_3', + inputDisplay: ( + + Value 3 + + ), + }, +]; + +const configSelect = { label: 'Config' }; + +const PercentageConfigSelect = ({ path }: { path: string }) => { + return ( + + ); +}; + +const ValueConfigSelect = ({ path }: { path: string }) => { + return ( + + ); +}; + +const percentageProcessorTypeConfig = { label: 'Processor type', defaultValue: 'percentage' }; + +const ProcessorTypeConfigurator = ({ basePath }: { basePath: string }) => { + const processorTypePath = \`\${basePath}.type\`; + const processorConfigPath = \`\${basePath}.config\`; + const [formData] = useFormData({ watch: processorTypePath }); + const processorType = get(formData, processorTypePath); + + const renderSelect = () => { + if (!processorType) { + return null; + } + + return processorType === 'percentage' ? ( + + ) : ( + + ); + }; + + return ( + + + + + {renderSelect()} + + ); +}; + +const ProcessorsConfigurator: FC<{ ruleType: string }> = ({ ruleType }) => { + return ( + + {({ items, addItem, removeItem }) => { + return ( + <> + {items.map(({ id, path }) => { + return ( + + + {/* Processor name */} + + + + {/* Processor type & config */} + + + {items.length > 1 && ( + + removeItem(id)} + aria-label="Remove processor" + /> + + )} + + ); + })} + + + {/* Add processor button */} + + Add processor + + + ); + }} + + ); +}; + +const defaultValue = { + ruleType: 'type_one', + processors_type_one: [ + { name: 'Processor 1 name', type: 'value', config: 'value_config_3' }, + { name: 'Processor 2 name', type: 'percentage', config: 'percentage_config_2' }, + ], +}; + +const schema = { + ruleType: { + label: 'Rule type', + defaultValue: 'type_one', + }, +}; + +const MyFormComponent = () => { + const { form } = useForm({ schema, defaultValue }); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ +

Rule configurator

+
+ + + {/* Rule type */} + + + + +

Processors

+
+ + {ruleType !== undefined && } + + Send + + ); +} + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_dynamic_data.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_dynamic_data.tsx new file mode 100644 index 0000000000000..a2c49d8b90911 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_dynamic_data.tsx @@ -0,0 +1,703 @@ +/* + * Copyright 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, { useCallback, useState, FC } from 'react'; +import { get } from 'lodash'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiButtonIcon, + EuiButtonEmpty, + EuiSpacer, + EuiTitle, + EuiHealth, + EuiLoadingSpinner, +} from '@elastic/eui'; + +import { TextField, SelectField, SuperSelectField } from '../../../components'; +import { fieldValidators } from '../../../helpers'; +import { useFormData } from '../../hooks'; +import { FormConfig } from '../../types'; +import { useFormContext } from '../../form_context'; +import { UseField } from '../use_field'; +import { UseArray } from '../use_array'; +import { FormWrapper } from './form_utils'; + +const { emptyField } = fieldValidators; + +// Select field options +const ruleTypeOptions = [ + { value: 'type_one', text: 'Type one' }, + { value: 'type_two', text: 'Type two' }, +]; + +const processorTypeOptions = [ + { value: 'percentage', text: 'Percentage' }, + { value: 'value', text: 'Value' }, +]; + +const percentageOptions = [ + { + value: 'percentage_config_1', + inputDisplay: ( + + Percentage 1 + + ), + }, + { + value: 'percentage_config_2', + inputDisplay: ( + + Percentage 2 + + ), + }, + { + value: 'percentage_config_3', + inputDisplay: ( + + Percentage 3 + + ), + }, +]; + +const valueOptions = [ + { + value: 'value_config_1', + inputDisplay: ( + + Value 1 + + ), + }, + { + value: 'value_config_2', + inputDisplay: ( + + Value 2 + + ), + }, + { + value: 'value_config_3', + inputDisplay: ( + + Value 3 + + ), + }, +]; + +// Dynamic data that we will be loaded in the form when selecting the rule "type one" +const processorsTypeOne = [ + { + name: 'DynamicTypeOne1', + type: 'value', + config: 'value_config_2', + }, + { + name: 'DynamicTypeOne2', + type: 'value', + config: 'value_config_3', + }, + { + name: 'DynamicTypeOne3', + type: 'percentage', + config: 'percentage_config_2', + }, +]; + +// Dynamic data that we will be loaded in the form when selecting the rule "type two" +const processorsTypeTwo = [ + { + name: 'DynamicTypeTwo1', + type: 'percentage', + config: 'percentage_config_2', + }, + { + name: 'DynamicTypeTwo2', + type: 'value', + config: 'value_config_3', + }, +]; + +// Form field configs +const processorConfig = { label: 'Config' }; +const percentageProcessorTypeConfig = { label: 'Processor type', defaultValue: 'percentage' }; + +const ProcessorTypeConfigurator = ({ + basePath, + readDefaultValueOnForm, +}: { + basePath: string; + readDefaultValueOnForm: boolean; +}) => { + const { getFields } = useFormContext(); + const processorTypePath = `${basePath}.type`; + const processorConfigPath = `${basePath}.config`; + const [formData] = useFormData({ + watch: [processorTypePath], + }); + + const processorType = get(formData, processorTypePath); + const options = processorType === 'percentage' ? percentageOptions : valueOptions; + const defaultOption = options[0].value; + + const onProcessorTypeChange = (newType: string) => { + const configSelectField = getFields()[processorConfigPath]; + + // Set the first select option from the list + configSelectField.setValue( + (newType === 'percentage' ? percentageOptions : valueOptions)[0].value + ); + }; + + const renderSelect = useCallback(() => { + if (!processorType) { + return null; + } + + return ( + + ); + }, [processorType, processorConfigPath, readDefaultValueOnForm, options, defaultOption]); + + return ( + + + + + {renderSelect()} + + ); +}; + +const processorNameConfig = { + label: 'Name', + validations: [{ validator: emptyField('A name is required.') }], +}; + +const ProcessorsConfigurator: FC<{ ruleType: string }> = ({ ruleType }) => { + return ( + + {({ items, addItem, removeItem }) => { + return ( + <> + {items.map(({ id, path, isNew }) => { + return ( + + + {/* Processor name */} + + + + {/* Processor type & config */} + + + {items.length > 1 && ( + + removeItem(id)} + aria-label="Remove processor" + /> + + )} + + ); + })} + + + {/* Add processor button */} + + Add processor + + + ); + }} + + ); +}; + +const FormContent: FC = () => { + const [isLoading, setIsLoading] = useState(false); + const { updateFieldValues } = useFormContext(); + const [{ ruleType }] = useFormData({ watch: 'ruleType' }); + + const onRuleTypeChange = useCallback( + (updatedRuleType: string) => { + if (!updatedRuleType) { + return; + } + + setIsLoading(true); + + // Simulate HTTP latency + setTimeout(() => { + updateFieldValues({ + // Set dynamically the processors based on the "ruleType" selected. + // In a real world scenario this would probably occur after fetching data on the server + processors: updatedRuleType === 'type_one' ? processorsTypeOne : processorsTypeTwo, + }); + + setIsLoading(false); + }, 500); + }, + [updateFieldValues] + ); + + return ( + <> + +

Rule configurator

+
+ + + {/* Rule type */} + + + + + + +

Processors

+
+
+ {isLoading && ( + + + + )} +
+ + {ruleType !== undefined && } + + ); +}; + +interface MyForm { + ruleType: string; + processors: Array<{ name: string; type: string; config: string }>; +} + +/** + * Form defaultValue - Loaded from backend + */ +const defaultValue = { + ruleType: 'type_two', + processors: [ + { name: 'TypeTwoName1', type: 'value', config: 'value_config_3' }, + { name: 'TypeTwoName2', type: 'percentage', config: 'percentage_config_2' }, + ], +}; + +/** Form schema */ +const schema = { + ruleType: { + label: 'Rule type', + helpText: 'Change the rule type to load other processor configurations', + defaultValue: 'type_one', + }, +}; + +const formConfig: FormConfig = { + schema, + defaultValue, +}; + +export function DynamicData() { + return ( + + + + ); +} + +DynamicData.storyName = 'Dynamic data'; + +DynamicData.parameters = { + docs: { + source: { + code: ` +// Select field options +const ruleTypeOptions = [ + { value: 'type_one', text: 'Type one' }, + { value: 'type_two', text: 'Type two' }, +]; + +const processorTypeOptions = [ + { value: 'percentage', text: 'Percentage' }, + { value: 'value', text: 'Value' }, +]; + +const percentageOptions = [ + { + value: 'percentage_config_1', + inputDisplay: ( + + Percentage 1 + + ), + }, + { + value: 'percentage_config_2', + inputDisplay: ( + + Percentage 2 + + ), + }, + { + value: 'percentage_config_3', + inputDisplay: ( + + Percentage 3 + + ), + }, +]; + +const valueOptions = [ + { + value: 'value_config_1', + inputDisplay: ( + + Value 1 + + ), + }, + { + value: 'value_config_2', + inputDisplay: ( + + Value 2 + + ), + }, + { + value: 'value_config_3', + inputDisplay: ( + + Value 3 + + ), + }, +]; + +// Dynamic data that we will be loaded in the form when selecting the rule "type one" +const processorsTypeOne = [ + { + name: 'DynamicTypeOne1', + type: 'value', + config: 'value_config_2', + }, + { + name: 'DynamicTypeOne2', + type: 'value', + config: 'value_config_3', + }, + { + name: 'DynamicTypeOne3', + type: 'percentage', + config: 'percentage_config_2', + }, +]; + +// Dynamic data that we will be loaded in the form when selecting the rule "type two" +const processorsTypeTwo = [ + { + name: 'DynamicTypeTwo1', + type: 'percentage', + config: 'percentage_config_2', + }, + { + name: 'DynamicTypeTwo2', + type: 'value', + config: 'value_config_3', + }, +]; + +// Form field configs +const processorConfig = { label: 'Config' }; +const percentageProcessorTypeConfig = { label: 'Processor type', defaultValue: 'percentage' }; + +const ProcessorTypeConfigurator = ({ + basePath, + readDefaultValueOnForm, +}: { + basePath: string; + readDefaultValueOnForm: boolean; +}) => { + const { getFields } = useFormContext(); + const processorTypePath = \`\${basePath}.type\`; + const processorConfigPath = \`\${basePath}.config\`; + const [formData] = useFormData({ + watch: [processorTypePath], + }); + + const processorType = get(formData, processorTypePath); + const options = processorType === 'percentage' ? percentageOptions : valueOptions; + const defaultOption = options[0].value; + + const onProcessorTypeChange = (newType: string) => { + const configSelectField = getFields()[processorConfigPath]; + + // Set the first select option from the list + configSelectField.setValue( + (newType === 'percentage' ? percentageOptions : valueOptions)[0].value + ); + }; + + const renderSelect = useCallback(() => { + if (!processorType) { + return null; + } + + return ( + + ); + }, [processorType, processorConfigPath, readDefaultValueOnForm, options, defaultOption]); + + return ( + + + + + {renderSelect()} + + ); +}; + +const processorNameConfig = { + label: 'Name', + validations: [{ validator: emptyField('A name is required.') }], +}; + +const ProcessorsConfigurator: FC<{ ruleType: string }> = ({ ruleType }) => { + return ( + + {({ items, addItem, removeItem }) => { + return ( + <> + {items.map(({ id, path, isNew }) => { + return ( + + + {/* Processor name */} + + + + {/* Processor type & config */} + + + {items.length > 1 && ( + + removeItem(id)} + aria-label="Remove processor" + /> + + )} + + ); + })} + + + {/* Add processor button */} + + Add processor + + + ); + }} + + ); +}; + +interface MyForm { + ruleType: string; + processors: Array<{ name: string; type: string; config: string }>; +} + +/** + * Form defaultValue - Loaded from backend + */ +const defaultValue = { + ruleType: 'type_two', + processors: [ + { name: 'TypeTwoName1', type: 'value', config: 'value_config_3' }, + { name: 'TypeTwoName2', type: 'percentage', config: 'percentage_config_2' }, + ], +}; + +/** Form schema */ +const schema = { + ruleType: { + label: 'Rule type', + helpText: 'Change the rule type to load other processor configurations', + defaultValue: 'type_one', + }, +}; + +const MyFormComponent = () => { + const { form } = useForm({ schema, defaultValue }); + + const [isLoading, setIsLoading] = useState(false); + const { updateFieldValues } = form; + const [{ ruleType }] = useFormData({ form, watch: 'ruleType' }); + + const onRuleTypeChange = useCallback( + (updatedRuleType: string) => { + if (!updatedRuleType) { + return; + } + + setIsLoading(true); + + // Simulate HTTP latency + setTimeout(() => { + updateFieldValues({ + // Set dynamically the processors based on the "ruleType" selected. + // In a real world scenario this would probably occur after fetching data on the server + processors: updatedRuleType === 'type_one' ? processorsTypeOne : processorsTypeTwo, + }); + + setIsLoading(false); + }, 500); + }, + [updateFieldValues] + ); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ +

Rule configurator

+
+ + + {/* Rule type */} + + + + + + +

Processors

+
+
+ {isLoading && ( + + + + )} +
+ + {ruleType !== undefined && } + + Send + + ); +} + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_reorder.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_reorder.tsx new file mode 100644 index 0000000000000..64472c69079ea --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_array_reorder.tsx @@ -0,0 +1,280 @@ +/* + * Copyright 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 { + EuiFlexGroup, + EuiFlexItem, + EuiButtonIcon, + EuiButtonEmpty, + EuiSpacer, + EuiDragDropContext, + EuiDroppable, + EuiDraggable, + EuiTitle, + DropResult, + EuiIcon, +} from '@elastic/eui'; + +import { TextField } from '../../../components'; +import { fieldValidators } from '../../../helpers'; +import { FormConfig } from '../../types'; +import { UseField } from '../use_field'; +import { UseArray } from '../use_array'; +import { FormWrapper } from './form_utils'; + +const { emptyField } = fieldValidators; + +const defaultValue = { + employees: [ + { + name: 'John', + lastName: 'Snow', + }, + { + name: 'Mick', + lastName: 'Jagger', + }, + { + name: 'Roger', + lastName: 'Federer', + }, + ], +}; + +const formConfig: FormConfig = { + defaultValue, +}; + +export function Reorder() { + return ( + + <> + +

Employees

+
+ + + + {({ items, addItem, removeItem, moveItem }) => { + const onDragEnd = ({ source, destination }: DropResult) => { + if (source && destination) { + moveItem(source.index, destination.index); + } + }; + + return ( + <> + + + <> + {items.map(({ id, path }, index) => { + return ( + + {(provided) => ( + + +
+ +
+
+ + + + + + + {items.length > 1 && ( + + removeItem(id)} + aria-label="Remove item" + /> + + )} +
+ )} +
+ ); + })} + +
+
+ + + + Add employee + + + ); + }} +
+ +
+ ); +} + +Reorder.storyName = 'Reorder'; + +Reorder.parameters = { + docs: { + source: { + code: ` +const defaultValue = { + employees: [ + { + name: 'John', + lastName: 'Snow', + }, + { + name: 'Mick', + lastName: 'Jagger', + }, + { + name: 'Roger', + lastName: 'Federer', + }, + ], +}; + +const MyFormComponent = () => { + const { form } = useForm({ defaultValue }); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ +

Employees

+
+ + + + {({ items, addItem, removeItem, moveItem }) => { + const onDragEnd = ({ source, destination }: DropResult) => { + if (source && destination) { + moveItem(source.index, destination.index); + } + }; + + return ( + <> + + + <> + {items.map(({ id, path }, index) => { + return ( + + {(provided) => ( + + +
+ +
+
+ + + + + + + {items.length > 1 && ( + + removeItem(id)} + aria-label="Remove item" + /> + + )} +
+ )} +
+ ); + })} + +
+
+ + + + Add employee + + + ); + }} +
+ + Send + + ); +} + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_field_change_listeners.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_field_change_listeners.tsx new file mode 100644 index 0000000000000..41bb15d5c47aa --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_field_change_listeners.tsx @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 } from 'react'; +import { action } from '@storybook/addon-actions'; +import { EuiText, EuiTextColor, EuiSpacer } from '@elastic/eui'; + +import { TextField } from '../../../components'; +import { useFormData } from '../../hooks/use_form_data'; +import { UseField } from '../use_field'; + +/** + * This Story outputs the order in which different state update + * and events occur whenever a field value changes. + */ +export const ChangeListeners = () => { + const onUseFormDataChange = ({ title }: { title: string }) => { + action('1. useFormData() -> onChange() handler')(title); + }; + const [{ title }] = useFormData({ watch: 'title', onChange: onUseFormDataChange }); + + const onFieldChangeProp = (value: string) => { + action('2. onChange() prop handler')(value); + }; + + useEffect(() => { + action('4. useEffect() "title" changed')(title); + action('')('----------------------------------'); + }, [title]); + + return ( + <> + +

+ + Info: start writing in the field and see the order of change listeners appear in the + "Actions" panel below. + +

+
+ + + path="title" + component={TextField} + config={{ + label: 'Title', + helpText: 'This is a help text for the field.', + validations: [ + { + validator: ({ value }) => { + action('3. Validating "title" field')(value); + }, + }, + ], + }} + onChange={onFieldChangeProp} + /> + + ); +}; + +ChangeListeners.storyName = 'ChangeListeners'; + +ChangeListeners.parameters = { + docs: { + source: { + code: ` +const MyFormComponent = () => { + const { form } = useForm({ defaultValue }); + + const onUseFormDataChange = ({ title }: { title: string }) => { + action('1. useFormData() -> onChange() handler')(title); + }; + const [{ title }] = useFormData({ watch: 'title', onChange: onUseFormDataChange }); + + const onFieldChangeProp = (value: string) => { + action('2. onChange() prop handler')(value); + }; + + useEffect(() => { + action('4. useEffect() "title" changed')(title); + action('')('----------------------------------'); + }, [title]); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ +

+ + Info: start writing in the field and see the order of change listeners appear in the + "Actions" panel below. + +

+
+ + + path="title" + component={TextField} + config={{ + label: 'Title', + helpText: 'This is a help text for the field.', + validations: [ + { + validator: ({ value }) => { + action('3. Validating "title" field')(value); + }, + }, + ], + }} + onChange={onFieldChangeProp} + /> + + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_field_field_types.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_field_field_types.tsx new file mode 100644 index 0000000000000..e179d7b5315ca --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_field_field_types.tsx @@ -0,0 +1,292 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { action } from '@storybook/addon-actions'; +import { EuiText, EuiTextColor, EuiSpacer, EuiHealth } from '@elastic/eui'; + +import { FieldConfig } from '../../types'; +import { + TextField, + TextAreaField, + NumericField, + ToggleField, + ComboBoxField, + CheckBoxField, + JsonEditorField, + MultiSelectField, + RadioGroupField, + RangeField, + SelectField, + SuperSelectField, +} from '../../../components'; +import { fieldFormatters } from '../../../helpers'; +import { UseField } from '../use_field'; + +const fieldTypeOptions = [ + 'checkBox', + 'comboBox', + 'jsonEditor', + 'multiSelect', + 'number', + 'radioGroup', + 'range', + 'select', + 'superSelect', + 'text', + 'textArea', + 'toggle', +] as const; + +type FieldType = typeof fieldTypeOptions[number]; + +const fieldConfigBase: FieldConfig = { + label: 'My field', +}; + +const getPropsForType = (type: FieldType) => { + switch (type) { + case 'text': + return { + component: TextField, + }; + case 'number': + return { + component: NumericField, + config: { + ...fieldConfigBase, + formatters: [fieldFormatters.toInt], + }, + }; + case 'toggle': + return { + component: ToggleField, + defaultValue: true, + }; + case 'checkBox': + return { + component: CheckBoxField, + defaultValue: true, + }; + case 'select': + return { + component: SelectField, + defaultValue: 'option_one', + componentProps: { + euiFieldProps: { + options: [ + { value: 'option_one', text: 'Option one' }, + { value: 'option_two', text: 'Option two' }, + { value: 'option_three', text: 'Option three' }, + ], + }, + }, + }; + case 'superSelect': + return { + component: SuperSelectField, + defaultValue: 'minor', + componentProps: { + euiFieldProps: { + options: [ + { + value: 'warning', + inputDisplay: ( + + Warning + + ), + disabled: true, + }, + { + value: 'minor', + inputDisplay: ( + + Minor + + ), + }, + { + value: 'critical', + inputDisplay: ( + + Critical + + ), + }, + ], + }, + }, + }; + case 'multiSelect': + // TODO: update MultiSelectField to use + // and + return { + component: MultiSelectField, + euiFieldProps: { + options: [ + { label: 'Johann Sebastian Bach', checked: 'on' }, + { label: 'Wolfgang Amadeus Mozart', checked: 'on' }, + { label: 'Antonín Dvořák', checked: 'off' }, + { label: 'Dmitri Shostakovich' }, + { label: 'Felix Mendelssohn-Bartholdy' }, + { label: 'Franz Liszt' }, + { label: 'Franz Schubert' }, + { label: 'Frédéric Chopin' }, + { label: 'Georg Friedrich Händel' }, + { label: 'Giuseppe Verdi' }, + { label: 'Gustav Mahler' }, + { label: 'Igor Stravinsky' }, + { label: 'Johannes Brahms' }, + { label: 'Joseph Haydn' }, + { label: 'Ludwig van Beethoven' }, + { label: 'Piotr Illitch Tchaïkovsky' }, + { label: 'Robert Schumann' }, + { label: 'Sergej S. Prokofiew' }, + ], + searchable: true, + }, + }; + case 'comboBox': + return { + component: ComboBoxField, + defaultValue: [], + }; + case 'jsonEditor': + return { + component: JsonEditorField, + defaultValue: '', + componentProps: { + euiCodeEditorProps: { + height: '280px', + }, + }, + }; + case 'radioGroup': + return { + component: RadioGroupField, + defaultValue: 'optionTwo', + euiFieldProps: { + options: [ + { + id: 'optionOne', + label: 'Option one', + }, + { + id: 'optionTwo', + label: 'Option two is checked by default', + }, + { + id: 'radioGroupItemThird', + label: 'Option three is disabled', + disabled: true, + }, + ], + }, + }; + case 'textArea': + return { + component: TextAreaField, + }; + case 'range': + return { + component: RangeField, + defaultValue: 3, + config: { + ...fieldConfigBase, + serializer: fieldFormatters.toInt, + }, + }; + default: + throw new Error(`No props found for ${type} type`); + } +}; + +interface Params { + fieldType: FieldType; +} + +export function FieldTypes({ fieldType }: Params) { + return ( + <> + +

+ + Info: change the field type in the "Controls" panel below. + +

+
+ + + // We add a key to force a reset of the state whenever + // the field type changes + key={fieldType} + path="myField" + config={{ ...fieldConfigBase }} + onChange={action('onChange')} + {...getPropsForType(fieldType)} + /> + + ); +} + +FieldTypes.args = { + fieldType: 'text', +}; + +FieldTypes.argTypes = { + fieldType: { + options: fieldTypeOptions, + control: { type: 'radio' }, + }, +}; + +FieldTypes.storyName = 'FieldTypes'; + +FieldTypes.parameters = { + docs: { + source: { + code: ` +const MyFormComponent = () => { + const { form } = useForm({ defaultValue }); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ +

+ + Info: change the field type in the "Controls" panel below. + +

+
+ + + // We add a key to force a reset of the state whenever + // the field type changes + key={fieldType} + path="myField" + config={{ ...fieldConfigBase }} + onChange={action('onChange')} + {...getPropsForType(fieldType)} + /> + + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_multi_field_basic.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_multi_field_basic.tsx new file mode 100644 index 0000000000000..dc3acf99c63a7 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/__stories__/use_multi_field_basic.tsx @@ -0,0 +1,143 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 } from 'react'; +import { EuiSpacer, EuiDualRange, EuiText, EuiTextColor, EuiFormRow } from '@elastic/eui'; +import { action } from '@storybook/addon-actions'; + +import { useFormData } from '../../hooks'; +import { UseMultiFields } from '../use_multi_fields'; + +const fields = { + min: { + path: 'minValue', + defaultValue: 0, + }, + max: { + path: 'maxValue', + defaultValue: 100, + }, +}; + +export function Basic() { + const [{ minValue: _min, maxValue: _max }] = useFormData(); + + useEffect(() => { + action('Min max values')([_min, _max]); + }, [_min, _max]); + + return ( + <> + +

+ + When you need to declare multiple fields you can use "UseMultiFields" to avoid + nesting multiple "UseField". + +

+
+ + + + fields={fields}> + {({ min, max }) => { + return ( + { + min.setValue(minValue as number); + max.setValue(maxValue as number); + }} + /> + ); + }} + + + + ); +} + +Basic.storyName = 'Basic'; + +Basic.parameters = { + docs: { + source: { + code: ` +const fields = { + min: { + path: 'minValue', + defaultValue: 0, + }, + max: { + path: 'maxValue', + defaultValue: 100, + }, +}; + +const MyFormComponent = () => { + const { form } = useForm({ defaultValue }); + + const [{ minValue: _min, maxValue: _max }] = useFormData(); + + useEffect(() => { + action('Min max values')([_min, _max]); + }, [_min, _max]); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ +

+ + When you need to declare multiple fields you can use "UseMultiFields" to avoid + nesting multiple "UseField". + +

+
+ + + + fields={fields}> + {({ min, max }) => { + return ( + { + min.setValue(minValue as number); + max.setValue(maxValue as number); + }} + /> + ); + }} + + + + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/form.stories.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/form.stories.tsx new file mode 100644 index 0000000000000..16afbbe21f9e8 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/form.stories.tsx @@ -0,0 +1,166 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { ComponentMeta } from '@storybook/react'; +import { EuiButton } from '@elastic/eui'; + +import { action } from '@storybook/addon-actions'; +import { TextField } from '../../components'; +import { STORYBOOK_SECTION } from '../constants'; +import { FormHook, FieldConfig } from '../types'; +import { useForm } from '../hooks/use_form'; +import { Form, Props as FormProps } from './form'; +import { UseField } from './use_field'; +import { formStories } from './__stories__'; + +export default { + component: Form, + title: `${STORYBOOK_SECTION}/Form`, + subcomponents: { UseField }, + decorators: [(Story) =>
{Story()}
], + parameters: { + controls: { hideNoControlsWarning: true }, + }, +} as ComponentMeta; + +type Args = Pick; + +const { DefaultValue, Validation, DeSerializer, IsModified, GlobalFields } = formStories; + +/** + * Validate the form and return its data. + * + * @param form The FormHook instance + */ +const submitForm = async (form: FormHook) => { + const { isValid, data } = await form.submit(); + action('Send form')({ + isValid, + data: JSON.stringify(data), + }); +}; + +/** + * The "title" field base configuration + */ +const titleConfigBase: FieldConfig = { + label: 'Title', + helpText: 'This is a help text for the field.', +}; + +// --- SIMPLE + +export const Simple = (args: Args) => { + const { form } = useForm(); + + return ( +
+ + path="title" + component={TextField} + config={{ + ...titleConfigBase, + }} + /> + submitForm(form)}>Send + + ); +}; + +Simple.parameters = { + docs: { + source: { + code: ` +const MyFormComponent = () => { + const { form } = useForm(); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ + path="title" + component={TextField} + config={{ + label: 'Title', + helpText: 'This is a help text for the field.', + }} + /> + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; + +// --- FORM SCHEMA + +const formSchema = { + title: { + ...titleConfigBase, + }, +}; + +export const Schema = (args: Args) => { + const { form } = useForm({ + schema: formSchema, + }); + + return ( +
+ path="title" component={TextField} /> + submitForm(form)}>Send + + ); +}; + +Schema.parameters = { + docs: { + source: { + code: ` +const formSchema = { + title: { + label: 'Title', + helpText: 'This is a help text for the field.', + }, +}; + +const MyFormComponent = () => { + const { form } = useForm({ + schema: formSchema, + }); + + const submitForm = async () => { + const { isValid, data } = await form.submit(); + if (isValid) { + // ... do something with the data + } + }; + + return ( +
+ path="title" component={TextField} /> + Send + + ); +}; + `, + language: 'tsx', + }, + }, +}; + +export { DefaultValue, Validation, DeSerializer, IsModified, GlobalFields }; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/form.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/form.tsx index 31d1c09712c93..99bffb44b5612 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/form.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/form.tsx @@ -13,7 +13,7 @@ import { FormProvider } from '../form_context'; import { FormDataContextProvider } from '../form_data_context'; import { FormHook } from '../types'; -interface Props { +export interface Props { form: FormHook; FormWrapper?: React.ComponentType; children: ReactNode | ReactNode[]; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.stories.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.stories.tsx new file mode 100644 index 0000000000000..c565481d0d0a6 --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.stories.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 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 { ComponentMeta } from '@storybook/react'; + +import { STORYBOOK_SECTION } from '../constants'; +import { UseArray } from './use_array'; +import { useArrayStories } from './__stories__'; + +const { UseArrayBasic, UseArrayReorder, UseArrayComplex, UseArrayDynamicData } = useArrayStories; + +export default { + component: UseArray, + title: `${STORYBOOK_SECTION}/UseArray`, + decorators: [ + (Story) => { + return ( +
+ +
+ ); + }, + ], +} as ComponentMeta; + +export { UseArrayBasic, UseArrayReorder, UseArrayComplex, UseArrayDynamicData }; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts index d6ada976c875c..7f5743ef134e8 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_array.ts @@ -13,7 +13,7 @@ import { getFieldValidityAndErrorMessage } from '../helpers'; import { useFormContext } from '../form_context'; import { useField, InternalFieldConfig } from '../hooks'; -interface Props { +export interface Props { path: string; initialNumberOfItems?: number; readDefaultValueOnForm?: boolean; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.stories.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.stories.tsx new file mode 100644 index 0000000000000..e280d8e4a944b --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.stories.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 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 { ComponentMeta } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; +import { EuiButton, EuiSpacer } from '@elastic/eui'; + +import { STORYBOOK_SECTION } from '../constants'; +import { FormHook } from '../types'; +import { useForm } from '../hooks/use_form'; + +import { Form } from './form'; +import { UseField } from './use_field'; +import { useFieldStories } from './__stories__'; + +const { UseFieldFieldTypes, UseFieldChangeListeners } = useFieldStories; + +/** + * Validate the form and return its data. + * + * @param form The FormHook instance + */ +const submitForm = async (form: FormHook) => { + const { isValid, data } = await form.submit(); + action('Send form')({ + isValid, + data: JSON.stringify(data), + }); +}; + +export default { + component: UseField, + title: `${STORYBOOK_SECTION}/UseField`, + decorators: [ + (Story) => { + const { form } = useForm(); + return ( +
+
+ <> + + + submitForm(form)}>Send + + +
+ ); + }, + ], +} as ComponentMeta; + +export { UseFieldFieldTypes, UseFieldChangeListeners }; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx index 7e216e3126ed8..86af10f08cc23 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx @@ -6,11 +6,10 @@ * Side Public License, v 1. */ -import React, { FunctionComponent, useMemo, useEffect } from 'react'; +import React, { FunctionComponent } from 'react'; -import { FieldHook, FieldConfig, FormData, FieldValidationData } from '../types'; -import { useField, InternalFieldConfig } from '../hooks'; -import { useFormContext } from '../form_context'; +import { FieldHook, FieldConfig, FormData } from '../types'; +import { useFieldFromProps } from '../hooks'; export interface Props { path: string; @@ -49,104 +48,13 @@ export interface Props { } function UseFieldComp(props: Props) { - const form = useFormContext(); - const { getFieldDefaultValue, __readFieldConfigFromSchema, __updateDefaultValueAt } = form; + const { field, propsToForward } = useFieldFromProps(props); - const { - path, - config = __readFieldConfigFromSchema(props.path), - defaultValue, - component, - componentProps, - readDefaultValueOnForm = true, - onChange, - onError, - children, - validationData, - validationDataProvider, - ...rest - } = props; - - const ComponentToRender = component ?? 'input'; - const propsToForward = { ...componentProps, ...rest }; - - const initialValue = useMemo(() => { - // The initial value of the field. - // Order in which we'll determine this value: - // 1. The "defaultValue" passed through prop - // --> - // 2. A value declared in the "defaultValue" object passed to the form when initiating - // --> const { form } = useForm({ defaultValue: { foo: 'bar' } })) - // 3. The "defaultValue" declared on the field "config". Either passed through prop or on the form schema - // a. --> - // b. --> const formSchema = { foo: { defaultValue: 'bar' } } - // 4. An empty string ("") - - if (defaultValue !== undefined) { - return defaultValue; // defaultValue passed through props - } - - let value: T | undefined; - - if (readDefaultValueOnForm) { - // Check the "defaultValue" object passed to the form - value = getFieldDefaultValue(path); - } - - if (value === undefined) { - // Check the field "config" object (passed through prop or declared on the form schema) - value = config?.defaultValue; - } - - // If still undefined return an empty string - return value === undefined ? ('' as unknown as T) : value; - }, [defaultValue, path, config, readDefaultValueOnForm, getFieldDefaultValue]); - - const fieldConfig = useMemo & InternalFieldConfig>( - () => ({ - ...config, - initialValue, - }), - [config, initialValue] - ); - - const fieldValidationData = useMemo( - () => ({ - validationData, - validationDataProvider, - }), - [validationData, validationDataProvider] - ); - - const field = useField( - form, - path, - fieldConfig, - onChange, - onError, - fieldValidationData - ); - - useEffect(() => { - let needsCleanUp = false; - - if (defaultValue !== undefined) { - needsCleanUp = true; - // Update the form "defaultValue" ref object. - // This allows us to reset the form and put back the defaultValue of each field - __updateDefaultValueAt(path, defaultValue); - } - - return () => { - if (needsCleanUp) { - __updateDefaultValueAt(path, undefined); - } - }; - }, [path, defaultValue, __updateDefaultValueAt]); + const ComponentToRender = props.component ?? 'input'; // Children prevails over anything else provided. - if (children) { - return children(field); + if (props.children) { + return props.children(field); } if (ComponentToRender === 'input') { diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_field.stories.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_field.stories.tsx new file mode 100644 index 0000000000000..0cefc77bda9fb --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_field.stories.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import React from 'react'; +import { ComponentMeta } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; +import { EuiButton, EuiSpacer } from '@elastic/eui'; + +import { STORYBOOK_SECTION } from '../constants'; +import { FormHook } from '../types'; +import { useForm } from '../hooks/use_form'; + +import { Form } from './form'; +import { UseField } from './use_field'; +import { UseMultiFields } from './use_multi_fields'; +import { useMultiFieldStories } from './__stories__'; + +const { UseMultiFieldBasic } = useMultiFieldStories; + +/** + * Validate the form and return its data. + * + * @param form The FormHook instance + */ +const submitForm = async (form: FormHook) => { + const { isValid, data } = await form.submit(); + action('Send form')({ + isValid, + data: JSON.stringify(data), + }); +}; + +export default { + component: UseMultiFields, + title: `${STORYBOOK_SECTION}/UseMultiFields`, + decorators: [ + (Story) => { + const { form } = useForm(); + return ( +
+
+ <> + + + submitForm(form)}>Send + + +
+ ); + }, + ], +} as ComponentMeta; + +export { UseMultiFieldBasic }; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.test.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.test.tsx new file mode 100644 index 0000000000000..94c36613c44ba --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.test.tsx @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import React, { useState } from 'react'; + +import { registerTestBed } from '../shared_imports'; +import { FieldHook } from '../types'; +import { useForm } from '../hooks/use_form'; +import { Form } from './form'; +import { UseMultiFields } from './use_multi_fields'; + +describe('', () => { + beforeAll(() => { + jest.useFakeTimers(); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + const fields = { + foo: { path: 'foo' }, + bar: { path: 'bar' }, + }; + + const TestComp = ({ onFields }: { onFields: (fields: { [x: string]: FieldHook }) => void }) => { + const { form } = useForm(); + const [stateFields, setStateFields] = useState<{ [key: string]: any }>(fields); + + const changeStateFields = () => { + // We'll make sure that if other fields are passed down after the initial + // rendering of the change does not create new FieldHook as that + // would break the **order** of hooks declared inside + + setStateFields({ + aaa: { path: 'aaa' }, // we add this field that will come first when sorting() A-Z + ...fields, + }); + }; + + return ( +
+ + {(hookFields) => { + onFields(hookFields); + return null; + }} + + +
+ ); + }; + + test('it should return 2 hook fields', () => { + const onFields = jest.fn(); + + const setup = registerTestBed(TestComp, { + defaultProps: { onFields }, + memoryRouter: { wrapComponent: false }, + }); + + setup(); + + expect(onFields).toHaveBeenCalled(); + const fieldsReturned = onFields.mock.calls[0][0]; + + expect(fieldsReturned.foo.path).toBe(fields.foo.path); + expect(fieldsReturned.foo.isPristine).toBeDefined(); // It's a FieldHook! + expect(fieldsReturned.bar.path).toBe(fields.bar.path); + expect(fieldsReturned.bar.isPristine).toBeDefined(); + }); + + test('it should keep a stable ref of initial fields passed', () => { + const onFields = jest.fn(); + + const setup = registerTestBed(TestComp, { + defaultProps: { onFields }, + memoryRouter: { wrapComponent: false }, + }); + + const { find } = setup(); + + expect(onFields).toBeCalledTimes(1); + let fieldsReturned = onFields.mock.calls[0][0] as { [key: string]: FieldHook }; + let paths = Object.values(fieldsReturned).map(({ path }) => path); + expect(paths).toEqual(['bar', 'foo']); + + // We change the fields passed down to + find('changeFields').simulate('click'); + expect(onFields).toBeCalledTimes(2); + fieldsReturned = onFields.mock.calls[1][0] as { [key: string]: FieldHook }; + paths = Object.values(fieldsReturned).map(({ path }) => path); + + // We still get the same 2 fields originally passed + expect(paths).toEqual(['bar', 'foo']); + }); +}); diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.tsx index 542be17a782f1..ac2bf5204c01d 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_multi_fields.tsx @@ -6,16 +6,15 @@ * Side Public License, v 1. */ -import React from 'react'; +import { useRef } from 'react'; -import { UseField, Props as UseFieldProps } from './use_field'; +import { Props as UseFieldProps } from './use_field'; +import { useFieldFromProps } from '../hooks'; import { FieldHook } from '../types'; -type FieldsArray = Array<{ id: string } & Omit, 'children'>>; - interface Props { fields: { [K in keyof T]: Exclude, 'children'> }; - children: (fields: { [K in keyof T]: FieldHook }) => JSX.Element; + children: (fields: { [K in keyof T]: FieldHook }) => JSX.Element | null; } /** @@ -59,7 +58,7 @@ const fields = { }, }; - + {({ min, max }) => { return ( ); }} - + ``` */ export function UseMultiFields({ fields, children }: Props) { - const fieldsArray = Object.entries(fields).reduce( - (acc, [fieldId, field]) => [...acc, { id: fieldId, ...(field as FieldHook) }], - [] as FieldsArray - ); + // Create a stable reference of fields Ids to prevent creating more fields + // by changing the "fields" prop. This is not allowed as it would break + // the hook order below. + const fieldIds = useRef(Object.keys(fields).sort() as Array); - const hookFields: { [K in keyof T]: FieldHook } = {} as any; + const hookFields = fieldIds.current.reduce((acc, id) => { + // We can disable the rules-of-hooks that prevents us to create a hook + // from inside a callback as we have the **guarantee** that the field hooks are created + // in the same order. - const renderField = (index: number) => { - const { id } = fieldsArray[index]; - return ( - - {(field) => { - hookFields[id as keyof T] = field; - return index === fieldsArray.length - 1 ? children(hookFields) : renderField(index + 1); - }} - - ); - }; + // eslint-disable-next-line react-hooks/rules-of-hooks + const { field } = useFieldFromProps(fields[id]); + return { + ...acc, + [id]: field, + }; + }, {} as { [K in keyof T]: FieldHook }); - if (!Boolean(fieldsArray.length)) { + if (!Boolean(fieldIds.current.length)) { return null; } - return renderField(0); + return children(hookFields); } diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/constants.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/constants.ts index c9886a789df20..93bcd590749e9 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/constants.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/constants.ts @@ -31,3 +31,5 @@ export const VALIDATION_TYPES = { /** If the field value is an Array, this error type would be returned if an _item_ of the array is invalid */ ARRAY_ITEM: 'arrayItem', }; + +export const STORYBOOK_SECTION = 'Form lib'; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/index.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/index.ts index f4911bfaadfa4..3f6c1ed53ab7f 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/index.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/index.ts @@ -8,6 +8,7 @@ export type { InternalFieldConfig } from './use_field'; export { useField } from './use_field'; +export { useFieldFromProps } from './use_field_from_props'; export { useForm } from './use_form'; export { useFormData } from './use_form_data'; export { useFormIsModified } from './use_form_is_modified'; diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field_from_props.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field_from_props.ts new file mode 100644 index 0000000000000..a3d36fd534b5d --- /dev/null +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field_from_props.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 { useMemo, useEffect } from 'react'; +import { UseFieldProps } from '../components'; +import { FieldHook, FieldConfig, FieldValidationData } from '../types'; +import { useFormContext } from '../form_context'; +import { useField, InternalFieldConfig } from './use_field'; + +/** + * Hook to initialize a FieldHook based on Props passed to or + * + * @param props The props passed to or + * @returns The field hook and props to forward to component to render for the field + */ + +export const useFieldFromProps = ( + props: UseFieldProps +): { field: FieldHook; propsToForward: { [x: string]: unknown } } => { + const form = useFormContext(); + const { getFieldDefaultValue, __readFieldConfigFromSchema, __updateDefaultValueAt } = form; + + const { + path, + config = __readFieldConfigFromSchema(props.path), + defaultValue, + component, + componentProps, + readDefaultValueOnForm = true, + onChange, + onError, + children, + validationData, + validationDataProvider, + ...rest + } = props; + + const initialValue = useMemo(() => { + // The initial value of the field. + // Order in which we'll determine this value: + // 1. The "defaultValue" passed through prop + // --> + // 2. A value declared in the "defaultValue" object passed to the form when initiating + // --> const { form } = useForm({ defaultValue: { foo: 'bar' } })) + // 3. The "defaultValue" declared on the field "config". Either passed through prop or on the form schema + // a. --> + // b. --> const formSchema = { foo: { defaultValue: 'bar' } } + // 4. An empty string ("") + + if (defaultValue !== undefined) { + return defaultValue; // defaultValue passed through props + } + + let value: T | undefined; + + if (readDefaultValueOnForm) { + // Check the "defaultValue" object passed to the form + value = getFieldDefaultValue(path); + } + + if (value === undefined) { + // Check the field "config" object (passed through prop or declared on the form schema) + value = config?.defaultValue; + } + + // If still undefined return an empty string + return value === undefined ? ('' as unknown as T) : value; + }, [defaultValue, path, config, readDefaultValueOnForm, getFieldDefaultValue]); + + const fieldConfig = useMemo & InternalFieldConfig>( + () => ({ + ...config, + initialValue, + }), + [config, initialValue] + ); + + const fieldValidationData = useMemo( + () => ({ + validationData, + validationDataProvider, + }), + [validationData, validationDataProvider] + ); + + const field = useField( + form, + path, + fieldConfig, + onChange, + onError, + fieldValidationData + ); + + useEffect(() => { + let needsCleanUp = false; + + if (defaultValue !== undefined) { + needsCleanUp = true; + // Update the form "defaultValue" ref object. + // This allows us to reset the form and put back the defaultValue of each field + __updateDefaultValueAt(path, defaultValue); + } + + return () => { + if (needsCleanUp) { + __updateDefaultValueAt(path, undefined); + } + }; + }, [path, defaultValue, __updateDefaultValueAt]); + + const propsToForward = { ...componentProps, ...rest }; + + return { field, propsToForward }; +}; diff --git a/src/plugins/es_ui_shared/tsconfig.json b/src/plugins/es_ui_shared/tsconfig.json index 90459058eec71..430ec5b85e4f7 100644 --- a/src/plugins/es_ui_shared/tsconfig.json +++ b/src/plugins/es_ui_shared/tsconfig.json @@ -11,7 +11,9 @@ "common/**/*", "public/**/*", "server/**/*", - "static/**/*" + "static/**/*", + "../../../typings/**/*", + ".storybook/**/*" ], "references": [ { "path": "../../core/tsconfig.json" }, diff --git a/src/plugins/field_formats/common/types.ts b/src/plugins/field_formats/common/types.ts index f52545408976e..8f19e6e26d32b 100644 --- a/src/plugins/field_formats/common/types.ts +++ b/src/plugins/field_formats/common/types.ts @@ -132,7 +132,7 @@ export type FieldFormatInstanceType = (new ( * TODO: support strict typing for params depending on format type * https://github.com/elastic/kibana/issues/108158 */ -export type FieldFormatParams = SerializableRecord; +export type FieldFormatParams

= SerializableRecord & P; /** * Params provided by the registry to every field formatter @@ -157,9 +157,12 @@ export type FieldFormatsStartCommon = Omit = { +export type SerializedFieldFormat< + P = {}, + TParams extends FieldFormatParams

= FieldFormatParams

+> = { id?: string; params?: TParams; }; -export type FormatFactory = (mapping?: SerializedFieldFormat) => IFieldFormat; +export type FormatFactory =

(mapping?: SerializedFieldFormat

) => IFieldFormat; diff --git a/src/plugins/home/public/application/components/guided_onboarding/__snapshots__/use_case_card.test.tsx.snap b/src/plugins/home/public/application/components/guided_onboarding/__snapshots__/use_case_card.test.tsx.snap index 4c66056e0338c..7ace627183237 100644 --- a/src/plugins/home/public/application/components/guided_onboarding/__snapshots__/use_case_card.test.tsx.snap +++ b/src/plugins/home/public/application/components/guided_onboarding/__snapshots__/use_case_card.test.tsx.snap @@ -14,23 +14,10 @@ exports[`use case card should render use case card component for observability 1 } display="subdued" - icon={ - - } image={ -

} onClick={[Function]} @@ -63,23 +50,10 @@ exports[`use case card should render use case card component for search 1`] = ` } display="subdued" - icon={ - - } image={ -
} onClick={[Function]} @@ -112,23 +86,10 @@ exports[`use case card should render use case card component for security 1`] = } display="subdued" - icon={ - - } image={ -
} onClick={[Function]} diff --git a/src/plugins/home/public/application/components/guided_onboarding/use_case_card.test.tsx b/src/plugins/home/public/application/components/guided_onboarding/use_case_card.test.tsx index b22bd49841f2f..b899d533572c7 100644 --- a/src/plugins/home/public/application/components/guided_onboarding/use_case_card.test.tsx +++ b/src/plugins/home/public/application/components/guided_onboarding/use_case_card.test.tsx @@ -12,11 +12,14 @@ import { shallow } from 'enzyme'; import { UseCaseCard } from './use_case_card'; jest.mock('../../kibana_services', () => { - const { applicationServiceMock } = jest.requireActual('@kbn/core/public/mocks'); + const { applicationServiceMock, uiSettingsServiceMock, httpServiceMock } = + jest.requireActual('@kbn/core/public/mocks'); return { getServices: () => ({ application: applicationServiceMock.createStartContract(), trackUiMetric: jest.fn(), + uiSettings: uiSettingsServiceMock.createStartContract(), + http: httpServiceMock.createStartContract(), }), }; }); diff --git a/src/plugins/home/public/application/components/guided_onboarding/use_case_card.tsx b/src/plugins/home/public/application/components/guided_onboarding/use_case_card.tsx index 599a321052ba0..cb5d765fc66c6 100644 --- a/src/plugins/home/public/application/components/guided_onboarding/use_case_card.tsx +++ b/src/plugins/home/public/application/components/guided_onboarding/use_case_card.tsx @@ -6,16 +6,8 @@ * Side Public License, v 1. */ -import React, { useMemo } from 'react'; -import { - EuiAvatar, - EuiCard, - EuiText, - EuiTitle, - IconType, - useEuiTheme, - useIsWithinBreakpoints, -} from '@elastic/eui'; +import React from 'react'; +import { EuiCard, EuiText, EuiTitle, EuiImage } from '@elastic/eui'; import { METRIC_TYPE } from '@kbn/analytics'; import { i18n } from '@kbn/i18n'; @@ -28,9 +20,8 @@ type UseCaseConstants = { title: string; description: string; }; - icon: { - type: IconType; - name: string; + logo: { + altText: string; }; navigateOptions: { appId: string; @@ -49,10 +40,9 @@ const constants: UseCaseConstants = { 'Create a finely-tuned search experience for your websites, applications, workplace content, and more.', }), }, - icon: { - type: 'inspect', - name: i18n.translate('home.guidedOnboarding.gettingStarted.search.iconName', { - defaultMessage: 'Enterprise Search icon', + logo: { + altText: i18n.translate('home.guidedOnboarding.gettingStarted.search.iconName', { + defaultMessage: 'Enterprise Search logo', }), }, navigateOptions: { @@ -73,10 +63,9 @@ const constants: UseCaseConstants = { } ), }, - icon: { - type: 'eye', - name: i18n.translate('home.guidedOnboarding.gettingStarted.observability.iconName', { - defaultMessage: 'Observability icon', + logo: { + altText: i18n.translate('home.guidedOnboarding.gettingStarted.observability.iconName', { + defaultMessage: 'Observability logo', }), }, navigateOptions: { @@ -94,10 +83,9 @@ const constants: UseCaseConstants = { 'Protect your environment against threats by unifying SIEM, endpoint security, and cloud security in one place.', }), }, - icon: { - type: 'securitySignal', - name: i18n.translate('home.guidedOnboarding.gettingStarted.security.iconName', { - defaultMessage: 'Security icon', + logo: { + altText: i18n.translate('home.guidedOnboarding.gettingStarted.security.iconName', { + defaultMessage: 'Security logo', }), }, navigateOptions: { @@ -113,7 +101,17 @@ export interface UseCaseProps { } export const UseCaseCard = ({ useCase }: UseCaseProps) => { - const { application, trackUiMetric } = getServices(); + const { application, trackUiMetric, uiSettings, http } = getServices(); + + const isDarkTheme = uiSettings.get('theme:darkMode'); + + const getImageUrl = (imageName: UseCase) => { + const imagePath = `/plugins/home/assets/solution_logos/${imageName}${ + isDarkTheme ? '_dark' : '' + }.png`; + + return http.basePath.prepend(imagePath); + }; const onUseCaseSelection = () => { trackUiMetric(METRIC_TYPE.CLICK, `guided_onboarding__use_case__${useCase}`); @@ -136,40 +134,11 @@ export const UseCaseCard = ({ useCase }: UseCaseProps) => {

{constants[useCase].i18nTexts.description}

); - - const { euiTheme } = useEuiTheme(); - const isSmallerBreakpoint = useIsWithinBreakpoints(['xs', 's']); - const isMediumBreakpoint = useIsWithinBreakpoints(['m']); - const cardCss = useMemo(() => { - return { - backgroundColor: - useCase === 'search' - ? euiTheme.colors.warning - : useCase === 'security' - ? euiTheme.colors.accent - : euiTheme.colors.success, - // smaller screens: taller cards (250px) - // medium screens: lower cards (150px) - // larger screens: tall but not too tall cards (200px) - minHeight: isSmallerBreakpoint ? 250 : isMediumBreakpoint ? 150 : 200, - }; - }, [euiTheme, isMediumBreakpoint, isSmallerBreakpoint, useCase]); - return ( - } - image={
} + image={} title={title} description={description} // Used for FS tracking diff --git a/src/plugins/home/public/assets/solution_logos/observability.png b/src/plugins/home/public/assets/solution_logos/observability.png new file mode 100644 index 0000000000000..b72753a98ce11 Binary files /dev/null and b/src/plugins/home/public/assets/solution_logos/observability.png differ diff --git a/src/plugins/home/public/assets/solution_logos/observability_dark.png b/src/plugins/home/public/assets/solution_logos/observability_dark.png new file mode 100644 index 0000000000000..721c88befe2df Binary files /dev/null and b/src/plugins/home/public/assets/solution_logos/observability_dark.png differ diff --git a/src/plugins/home/public/assets/solution_logos/search.png b/src/plugins/home/public/assets/solution_logos/search.png new file mode 100644 index 0000000000000..94d8ed4578ec5 Binary files /dev/null and b/src/plugins/home/public/assets/solution_logos/search.png differ diff --git a/src/plugins/home/public/assets/solution_logos/search_dark.png b/src/plugins/home/public/assets/solution_logos/search_dark.png new file mode 100644 index 0000000000000..8dcc5ae3882aa Binary files /dev/null and b/src/plugins/home/public/assets/solution_logos/search_dark.png differ diff --git a/src/plugins/home/public/assets/solution_logos/security.png b/src/plugins/home/public/assets/solution_logos/security.png new file mode 100644 index 0000000000000..10fea25c9db83 Binary files /dev/null and b/src/plugins/home/public/assets/solution_logos/security.png differ diff --git a/src/plugins/home/public/assets/solution_logos/security_dark.png b/src/plugins/home/public/assets/solution_logos/security_dark.png new file mode 100644 index 0000000000000..a96743cc3f0d5 Binary files /dev/null and b/src/plugins/home/public/assets/solution_logos/security_dark.png differ diff --git a/src/plugins/telemetry/public/mocks.ts b/src/plugins/telemetry/public/mocks.ts index 7c74d8f7d8813..42225703163e6 100644 --- a/src/plugins/telemetry/public/mocks.ts +++ b/src/plugins/telemetry/public/mocks.ts @@ -40,6 +40,7 @@ export function mockTelemetryService({ allowChangingOptInStatus: true, telemetryNotifyUserAboutOptInDefault: true, userCanChangeSettings: true, + labels: {}, ...configOverride, }; diff --git a/src/plugins/telemetry/public/plugin.ts b/src/plugins/telemetry/public/plugin.ts index d6d0288cbb0bf..6bf53d59cb215 100644 --- a/src/plugins/telemetry/public/plugin.ts +++ b/src/plugins/telemetry/public/plugin.ts @@ -21,6 +21,7 @@ import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/publ import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import { ElasticV3BrowserShipper } from '@kbn/analytics-shippers-elastic-v3-browser'; +import { of } from 'rxjs'; import { TelemetrySender, TelemetryService, TelemetryNotifications } from './services'; import type { TelemetrySavedObjectAttributes, @@ -104,6 +105,8 @@ export interface TelemetryPluginConfig { userCanChangeSettings?: boolean; /** Should we hide the privacy statement notice? Useful on some environments, e.g. Cloud */ hidePrivacyStatement?: boolean; + /** Extra labels to add to the telemetry context */ + labels: Record; } function getTelemetryConstants(docLinks: DocLinksStart): TelemetryConstants { @@ -146,6 +149,19 @@ export class TelemetryPlugin implements Plugin, Type<'staging'>] = [ schema.literal('prod'), @@ -32,6 +33,8 @@ const configSchema = schema.object({ sendUsageFrom: schema.oneOf([schema.literal('server'), schema.literal('browser')], { defaultValue: 'server', }), + // Used for extra enrichment of telemetry + labels: labelsSchema, }); export type TelemetryConfigType = TypeOf; @@ -45,6 +48,7 @@ export const config: PluginConfigDescriptor = { sendUsageFrom: true, sendUsageTo: true, hidePrivacyStatement: true, + labels: true, }, deprecations: () => [ (cfg) => { diff --git a/src/plugins/telemetry/server/config/index.ts b/src/plugins/telemetry/server/config/index.ts index 19ccd73e17fcd..da368f2cbd1aa 100644 --- a/src/plugins/telemetry/server/config/index.ts +++ b/src/plugins/telemetry/server/config/index.ts @@ -8,3 +8,4 @@ export { config } from './config'; export type { TelemetryConfigType } from './config'; +export type { TelemetryConfigLabels } from './telemetry_labels'; diff --git a/src/plugins/telemetry/server/config/telemetry_labels.ts b/src/plugins/telemetry/server/config/telemetry_labels.ts new file mode 100644 index 0000000000000..f8cf7e6575866 --- /dev/null +++ b/src/plugins/telemetry/server/config/telemetry_labels.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { schema, TypeOf } from '@kbn/config-schema'; + +/** + * Labels to enrich the context of the telemetry generated. + * When adding new keys, bear in mind that this info is exposed + * to the browser **even to unauthenticated pages**. + */ +export const labelsSchema = schema.object( + { + branch: schema.maybe(schema.string()), + ciBuildJobId: schema.maybe(schema.string()), + ciBuildId: schema.maybe(schema.string()), + ciBuildNumber: schema.maybe(schema.number()), + ftrConfig: schema.maybe(schema.string()), + git_rev: schema.maybe(schema.string()), + isPr: schema.maybe(schema.boolean()), + prId: schema.maybe(schema.string()), + journeyName: schema.maybe(schema.string()), + testBuildId: schema.maybe(schema.string()), + testJobId: schema.maybe(schema.string()), + }, + { defaultValue: {} } +); + +export type TelemetryConfigLabels = TypeOf; diff --git a/src/plugins/telemetry/server/plugin.ts b/src/plugins/telemetry/server/plugin.ts index cf2f7710e8729..9fe6ad52a8c3e 100644 --- a/src/plugins/telemetry/server/plugin.ts +++ b/src/plugins/telemetry/server/plugin.ts @@ -19,6 +19,7 @@ import { takeUntil, tap, shareReplay, + map, } from 'rxjs'; import { ElasticV3ServerShipper } from '@kbn/analytics-shippers-elastic-v3-server'; @@ -45,7 +46,7 @@ import { registerTelemetryUsageCollector, registerTelemetryPluginUsageCollector, } from './collectors'; -import type { TelemetryConfigType } from './config'; +import type { TelemetryConfigLabels, TelemetryConfigType } from './config'; import { FetcherTask } from './fetcher'; import { getTelemetrySavedObject, TelemetrySavedObject } from './telemetry_repository'; import { OPT_IN_POLL_INTERVAL_MS } from '../common/constants'; @@ -157,6 +158,19 @@ export class TelemetryPlugin implements Plugin({ + name: 'telemetry labels', + context$: this.config$.pipe(map(({ labels }) => ({ labels }))), + schema: { + labels: { + type: 'pass_through', + _meta: { + description: 'Custom labels added to the telemetry.labels config in the kibana.yml', + }, + }, + }, + }); + const config$ = this.config$; const isDev = this.isDev; registerCollection(telemetryCollectionManager); diff --git a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap index 9cd03e02f36dc..f590a5c82a79b 100644 --- a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap +++ b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap @@ -264,6 +264,7 @@ exports[`TelemetryManagementSectionComponent renders null because allowChangingO "defaultConfig": Object { "allowChangingOptInStatus": false, "banner": true, + "labels": Object {}, "optIn": true, "sendUsageFrom": "browser", "sendUsageTo": "staging", diff --git a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx index f747e9c6194db..7576c0f35b6a9 100644 --- a/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx +++ b/src/plugins/telemetry_management_section/public/components/telemetry_management_section.test.tsx @@ -30,6 +30,7 @@ describe('TelemetryManagementSectionComponent', () => { allowChangingOptInStatus: true, optIn: true, sendUsageFrom: 'browser', + labels: {}, }, isScreenshotMode: false, reportOptInStatusChange: false, @@ -61,6 +62,7 @@ describe('TelemetryManagementSectionComponent', () => { optIn: false, sendUsageFrom: 'browser', sendUsageTo: 'staging', + labels: {}, }, isScreenshotMode: false, reportOptInStatusChange: false, @@ -112,6 +114,7 @@ describe('TelemetryManagementSectionComponent', () => { optIn: false, sendUsageTo: 'staging', sendUsageFrom: 'browser', + labels: {}, }, isScreenshotMode: false, reportOptInStatusChange: false, @@ -157,6 +160,7 @@ describe('TelemetryManagementSectionComponent', () => { optIn: true, sendUsageTo: 'staging', sendUsageFrom: 'browser', + labels: {}, }, isScreenshotMode: false, reportOptInStatusChange: false, @@ -193,6 +197,7 @@ describe('TelemetryManagementSectionComponent', () => { optIn: false, sendUsageTo: 'staging', sendUsageFrom: 'browser', + labels: {}, }, isScreenshotMode: false, reportOptInStatusChange: false, @@ -233,6 +238,7 @@ describe('TelemetryManagementSectionComponent', () => { optIn: false, sendUsageTo: 'staging', sendUsageFrom: 'browser', + labels: {}, }, isScreenshotMode: false, reportOptInStatusChange: false, @@ -280,6 +286,7 @@ describe('TelemetryManagementSectionComponent', () => { optIn: false, sendUsageTo: 'staging', sendUsageFrom: 'browser', + labels: {}, }, isScreenshotMode: false, reportOptInStatusChange: false, diff --git a/src/plugins/visualizations/public/visualize_app/utils/utils.ts b/src/plugins/visualizations/public/visualize_app/utils/utils.ts index 70ffae134aacf..f122b301af1f8 100644 --- a/src/plugins/visualizations/public/visualize_app/utils/utils.ts +++ b/src/plugins/visualizations/public/visualize_app/utils/utils.ts @@ -102,5 +102,5 @@ export function getVizEditorOriginatingAppUrl(history: History) { } export function isFallbackDataView(dataView?: DataView): dataView is DataView { - return Boolean(dataView && !Object.keys(dataView.getOriginalSavedObjectBody() ?? {}).length); + return Boolean(dataView && !dataView.isPersisted()); } diff --git a/test/analytics/tests/instrumented_events/from_the_browser/click.ts b/test/analytics/tests/instrumented_events/from_the_browser/click.ts index 56e33b13ff6c2..dcf405825e90b 100644 --- a/test/analytics/tests/instrumented_events/from_the_browser/click.ts +++ b/test/analytics/tests/instrumented_events/from_the_browser/click.ts @@ -13,7 +13,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const ebtUIHelper = getService('kibana_ebt_ui'); const { common } = getPageObjects(['common']); - describe('General "click"', () => { + // FLAKY: https://github.com/elastic/kibana/issues/133800 + describe.skip('General "click"', () => { beforeEach(async () => { await common.navigateToApp('home'); // Just clicking the top-nav-button and expecting it's still there... we're just testing the click event generation diff --git a/test/api_integration/apis/index_patterns/index_pattern_crud/create_index_pattern/main.ts b/test/api_integration/apis/index_patterns/index_pattern_crud/create_index_pattern/main.ts index 43c9696fd11f8..6b6a84e539da3 100644 --- a/test/api_integration/apis/index_patterns/index_pattern_crud/create_index_pattern/main.ts +++ b/test/api_integration/apis/index_patterns/index_pattern_crud/create_index_pattern/main.ts @@ -243,7 +243,7 @@ export default function ({ getService }: FtrProviderContext) { expect(response.body[config.serviceKey].fieldAttrs.foo.customLabel).to.be('test'); }); - describe('when creating index pattern with existing title', () => { + describe('when creating index pattern with existing name', () => { it('returns error, by default', async () => { const title = `foo-${Date.now()}-${Math.random()}*`; const response1 = await supertest.post(config.path).send({ diff --git a/test/common/config.js b/test/common/config.js index 5079d32909ff5..f69afd4e789b5 100644 --- a/test/common/config.js +++ b/test/common/config.js @@ -51,6 +51,8 @@ export default function () { `--server.maxPayload=1679958`, // newsfeed mock service `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'newsfeed')}`, + // otel mock service + `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'otel_metrics')}`, `--newsfeed.service.urlRoot=${servers.kibana.protocol}://${servers.kibana.hostname}:${servers.kibana.port}`, `--newsfeed.service.pathTemplate=/api/_newsfeed-FTS-external-service-simulators/kibana/v{VERSION}.json`, // code coverage reporting plugin diff --git a/test/common/fixtures/plugins/otel_metrics/kibana.json b/test/common/fixtures/plugins/otel_metrics/kibana.json new file mode 100644 index 0000000000000..f9cc773c1fe0a --- /dev/null +++ b/test/common/fixtures/plugins/otel_metrics/kibana.json @@ -0,0 +1,15 @@ +{ + "id": "openTelemetryInstrumentedPlugin", + "owner": { + "name": "Stack Monitoring", + "githubTeam": "stack-monitoring-ui" + }, + "version": "1.0.0", + "kibanaVersion": "kibana", + "requiredPlugins": [ + "monitoringCollection" + ], + "optionalPlugins": [], + "server": true, + "ui": false +} \ No newline at end of file diff --git a/test/common/fixtures/plugins/otel_metrics/server/index.ts b/test/common/fixtures/plugins/otel_metrics/server/index.ts new file mode 100644 index 0000000000000..eb5f587592cae --- /dev/null +++ b/test/common/fixtures/plugins/otel_metrics/server/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. + */ + +import { OpenTelemetryUsageTest } from './plugin'; + +export const plugin = () => new OpenTelemetryUsageTest(); diff --git a/test/common/fixtures/plugins/otel_metrics/server/monitoring/metrics.ts b/test/common/fixtures/plugins/otel_metrics/server/monitoring/metrics.ts new file mode 100644 index 0000000000000..044cd7bee5441 --- /dev/null +++ b/test/common/fixtures/plugins/otel_metrics/server/monitoring/metrics.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Counter, Meter } from '@opentelemetry/api-metrics'; + +export class Metrics { + requestCounter: Counter; + + constructor(meter: Meter) { + this.requestCounter = meter.createCounter('request_count', { + description: 'Counts total number of requests', + }); + } +} diff --git a/test/common/fixtures/plugins/otel_metrics/server/plugin.ts b/test/common/fixtures/plugins/otel_metrics/server/plugin.ts new file mode 100644 index 0000000000000..65dec472b94f9 --- /dev/null +++ b/test/common/fixtures/plugins/otel_metrics/server/plugin.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CoreSetup, Plugin } from '@kbn/core/server'; +import { metrics } from '@opentelemetry/api-metrics'; +import { generateOtelMetrics } from './routes'; +import { Metrics } from './monitoring/metrics'; + +export class OpenTelemetryUsageTest implements Plugin { + private metrics: Metrics; + + constructor() { + this.metrics = new Metrics(metrics.getMeter('dummyMetric')); + } + + public setup(core: CoreSetup) { + const router = core.http.createRouter(); + generateOtelMetrics(router, this.metrics); + } + + public start() {} + public stop() {} +} diff --git a/test/common/fixtures/plugins/otel_metrics/server/routes/generate_otel_metrics.ts b/test/common/fixtures/plugins/otel_metrics/server/routes/generate_otel_metrics.ts new file mode 100644 index 0000000000000..6809059ca1472 --- /dev/null +++ b/test/common/fixtures/plugins/otel_metrics/server/routes/generate_otel_metrics.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { IKibanaResponse, IRouter } from '@kbn/core/server'; +import { Metrics } from '../monitoring/metrics'; + +export const generateOtelMetrics = (router: IRouter, metrics: Metrics) => { + router.post( + { + path: '/api/generate_otel_metrics', + validate: {}, + }, + async function (_context, _req, res): Promise> { + metrics.requestCounter.add(1); + return res.ok({}); + } + ); +}; diff --git a/test/common/fixtures/plugins/otel_metrics/server/routes/index.ts b/test/common/fixtures/plugins/otel_metrics/server/routes/index.ts new file mode 100644 index 0000000000000..49ac53bcf5412 --- /dev/null +++ b/test/common/fixtures/plugins/otel_metrics/server/routes/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 * from './generate_otel_metrics'; diff --git a/test/examples/config.js b/test/examples/config.js index 25537a22e19ac..e2374d203d7c7 100644 --- a/test/examples/config.js +++ b/test/examples/config.js @@ -9,15 +9,15 @@ import { resolve } from 'path'; import { services } from '../plugin_functional/services'; import fs from 'fs'; -import { KIBANA_ROOT } from '@kbn/test'; +import { REPO_ROOT } from '@kbn/utils'; export default async function ({ readConfigFile }) { const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); // Find all folders in /examples and /x-pack/examples since we treat all them as plugin folder - const examplesFiles = fs.readdirSync(resolve(KIBANA_ROOT, 'examples')); + const examplesFiles = fs.readdirSync(resolve(REPO_ROOT, 'examples')); const examples = examplesFiles.filter((file) => - fs.statSync(resolve(KIBANA_ROOT, 'examples', file)).isDirectory() + fs.statSync(resolve(REPO_ROOT, 'examples', file)).isDirectory() ); return { @@ -63,7 +63,7 @@ export default async function ({ readConfigFile }) { '--env.name=development', '--telemetry.optIn=false', ...examples.map( - (exampleDir) => `--plugin-path=${resolve(KIBANA_ROOT, 'examples', exampleDir)}` + (exampleDir) => `--plugin-path=${resolve(REPO_ROOT, 'examples', exampleDir)}` ), ], }, diff --git a/test/functional/apps/console/_console.ts b/test/functional/apps/console/_console.ts index de4ed241f4110..4f7c3664721e8 100644 --- a/test/functional/apps/console/_console.ts +++ b/test/functional/apps/console/_console.ts @@ -124,6 +124,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); + describe('with query params', () => { + it('should issue a successful request', async () => { + await PageObjects.console.clearTextArea(); + await PageObjects.console.enterRequest( + '\n GET _cat/aliases?format=json&v=true&pretty=true' + ); + await PageObjects.console.clickPlay(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await retry.try(async () => { + const status = await PageObjects.console.getResponseStatus(); + expect(status).to.eql(200); + }); + }); + }); + describe('multiple requests output', () => { const sendMultipleRequests = async (requests: string[]) => { await asyncForEach(requests, async (request) => { @@ -155,29 +171,26 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/135914 - describe.skip('with folded/unfolded lines in request body', () => { + describe('with folded/unfolded lines in request body', () => { const enterRequestWithBody = async () => { await PageObjects.console.enterRequest(); await PageObjects.console.pressEnter(); await PageObjects.console.enterText('{\n\t\t"_source": []'); }; - it('should save the state of folding/unfolding when navigating back to Console', async () => { + it('should restore the state of folding/unfolding when navigating back to Console', async () => { await PageObjects.console.clearTextArea(); await enterRequestWithBody(); await PageObjects.console.clickFoldWidget(); await PageObjects.common.navigateToApp('home'); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.common.navigateToApp('console'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.console.dismissTutorial(); expect(await PageObjects.console.hasFolds()).to.be(true); }); - it('should save the state of folding/unfolding when the page reloads', async () => { - // blocks the close help button for several seconds so just retry until we can click it. - await retry.try(async () => { - await PageObjects.console.collapseHelp(); - }); + it('should restore the state of folding/unfolding when the page reloads', async () => { await PageObjects.console.clearTextArea(); await enterRequestWithBody(); await PageObjects.console.clickFoldWidget(); diff --git a/test/functional/apps/context/_filters.ts b/test/functional/apps/context/_filters.ts index e8a8675e85f82..8c77d4fd013c1 100644 --- a/test/functional/apps/context/_filters.ts +++ b/test/functional/apps/context/_filters.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; const TEST_INDEX_PATTERN = 'logstash-*'; @@ -19,6 +20,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const filterBar = getService('filterBar'); const testSubjects = getService('testSubjects'); const retry = getService('retry'); + const browser = getService('browser'); const PageObjects = getPageObjects(['common', 'context']); @@ -75,5 +77,66 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { return await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, 'exists', true); }); }); + + const addPinnedFilter = async () => { + await filterBar.addFilter(TEST_ANCHOR_FILTER_FIELD, 'IS', TEST_ANCHOR_FILTER_VALUE); + await filterBar.toggleFilterPinned(TEST_ANCHOR_FILTER_FIELD); + }; + + const everyFieldMatches = async (matches: (field: string[]) => boolean) => { + const fields = await dataGrid.getFields(); + return fields.every(matches); + }; + + it('should update the data grid when a pinned filter is modified', async function () { + await addPinnedFilter(); + await PageObjects.context.waitUntilContextLoadingHasFinished(); + expect(await everyFieldMatches((field) => field[2] === TEST_ANCHOR_FILTER_VALUE)).to.be(true); + await filterBar.toggleFilterNegated(TEST_ANCHOR_FILTER_FIELD); + await PageObjects.context.waitUntilContextLoadingHasFinished(); + expect(await everyFieldMatches((field) => field[2] === TEST_ANCHOR_FILTER_VALUE)).to.be( + false + ); + }); + + const expectFiltersToExist = async () => { + expect(await filterBar.getFilterCount()).to.be(2); + expect( + await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, TEST_ANCHOR_FILTER_VALUE, true, true) + ).to.be(true); + expect(await filterBar.hasFilter('extension', 'png')).to.be(true); + expect( + await everyFieldMatches( + (field) => field[1] === 'png' && field[2] === TEST_ANCHOR_FILTER_VALUE + ) + ).to.be(true); + }; + + it('should preserve filters when the page is refreshed', async function () { + await addPinnedFilter(); + await filterBar.addFilter('extension', 'IS', 'png'); + await PageObjects.context.waitUntilContextLoadingHasFinished(); + await expectFiltersToExist(); + await browser.refresh(); + await PageObjects.context.waitUntilContextLoadingHasFinished(); + await expectFiltersToExist(); + }); + + it('should update filters when navigating forward and backward in history', async () => { + await filterBar.addFilter('extension', 'IS', 'png'); + await PageObjects.context.waitUntilContextLoadingHasFinished(); + expect(await filterBar.getFilterCount()).to.be(1); + expect(await filterBar.hasFilter('extension', 'png')).to.be(true); + expect(await everyFieldMatches((field) => field[1] === 'png')).to.be(true); + await browser.goBack(); + await PageObjects.context.waitUntilContextLoadingHasFinished(); + expect(await filterBar.getFilterCount()).to.be(0); + expect(await everyFieldMatches((field) => field[1] === 'png')).to.be(false); + await browser.goForward(); + await PageObjects.context.waitUntilContextLoadingHasFinished(); + expect(await filterBar.getFilterCount()).to.be(1); + expect(await filterBar.hasFilter('extension', 'png')).to.be(true); + expect(await everyFieldMatches((field) => field[1] === 'png')).to.be(true); + }); }); } diff --git a/test/functional/apps/dashboard_elements/controls/controls_callout.ts b/test/functional/apps/dashboard_elements/controls/controls_callout.ts index 73bf8fb50c241..0883957c37d8a 100644 --- a/test/functional/apps/dashboard_elements/controls/controls_callout.ts +++ b/test/functional/apps/dashboard_elements/controls/controls_callout.ts @@ -11,8 +11,12 @@ import { OPTIONS_LIST_CONTROL } from '@kbn/controls-plugin/common'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { + const kibanaServer = getService('kibanaServer'); + const browser = getService('browser'); const testSubjects = getService('testSubjects'); const dashboardAddPanel = getService('dashboardAddPanel'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const { dashboardControls, timePicker, dashboard } = getPageObjects([ 'dashboardControls', 'timePicker', @@ -25,12 +29,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('callout visibility', async () => { before(async () => { await dashboard.gotoDashboardLandingPage(); + await dashboard.clickNewDashboard(); await timePicker.setDefaultDataRange(); await dashboard.saveDashboard('Test Controls Callout'); }); describe('does not show the empty control callout on an empty dashboard', async () => { + before(async () => { + const panelCount = await dashboard.getPanelCount(); + if (panelCount > 0) { + const panels = await dashboard.getAllPanels(); + for (const panel of panels) { + await dashboardPanelActions.removePanel(panel); + } + await dashboard.clickQuickSave(); + } + }); + it('in view mode', async () => { await dashboard.clickCancelOutOfEditMode(); await testSubjects.missingOrFail('controls-empty'); @@ -44,7 +60,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('show the empty control callout on a dashboard with panels', async () => { await dashboard.switchToEditMode(); - await dashboardAddPanel.addVisualization('Rendering-Test:-animal-sounds-pie'); + const panelCount = await dashboard.getPanelCount(); + if (panelCount < 1) { + await dashboardAddPanel.addVisualization('Rendering-Test:-animal-sounds-pie'); + } await testSubjects.existOrFail('controls-empty'); }); @@ -57,6 +76,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.missingOrFail('controls-empty'); }); + it('deleting all controls shows the emoty control callout again', async () => { + await dashboardControls.deleteAllControls(); + await testSubjects.existOrFail('controls-empty'); + }); + + it('hide callout when hide announcement setting is true', async () => { + await dashboard.clickQuickSave(); + await dashboard.gotoDashboardLandingPage(); + await kibanaServer.uiSettings.update({ hideAnnouncements: true }); + await browser.refresh(); + + await dashboard.loadSavedDashboard('Test Controls Callout'); + await dashboard.switchToEditMode(); + await testSubjects.missingOrFail('controls-empty'); + + await kibanaServer.uiSettings.update({ hideAnnouncements: false }); + }); + after(async () => { await dashboard.clickCancelOutOfEditMode(); await dashboard.gotoDashboardLandingPage(); diff --git a/test/functional/apps/discover/_context_encoded_url_params.ts b/test/functional/apps/discover/_context_encoded_url_params.ts index cff83b2d6f645..94262b341885e 100644 --- a/test/functional/apps/discover/_context_encoded_url_params.ts +++ b/test/functional/apps/discover/_context_encoded_url_params.ts @@ -24,7 +24,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await security.testUser.setRoles(['kibana_admin', 'context_encoded_param']); await PageObjects.common.navigateToApp('settings'); await es.transport.request({ - path: `/context-encoded-param/_doc/${customDocIdParam}`, + path: `/context_encoded_param/_doc/${customDocIdParam}`, method: 'PUT', body: { username: 'Dmitry', @@ -32,7 +32,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, }); await PageObjects.settings.createIndexPattern( - 'context-encoded-param', + 'context_encoded_param', '@timestamp', true, customDataViewIdParam @@ -42,7 +42,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should navigate correctly', async () => { - await PageObjects.discover.selectIndexPattern('context-encoded-param'); + await PageObjects.discover.selectIndexPattern('context_encoded_param'); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.discover.waitForDocTableLoadingComplete(); diff --git a/test/functional/apps/discover/_data_grid_row_navigation.ts b/test/functional/apps/discover/_data_grid_row_navigation.ts index 9cd8adcc0e548..d2f91cb97ac59 100644 --- a/test/functional/apps/discover/_data_grid_row_navigation.ts +++ b/test/functional/apps/discover/_data_grid_row_navigation.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dataGrid = getService('dataGrid'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'settings']); + const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'settings', 'header']); const es = getService('es'); const security = getService('security'); @@ -30,32 +30,31 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('discover data grid row navigation', function () { before(async () => { - await security.testUser.setRoles(['kibana_admin', 'similar-index']); - await security.testUser.setRoles(['kibana_admin', 'similar-index-two']); + await security.testUser.setRoles(['kibana_admin', 'similar_index', 'similar_index_two']); await PageObjects.common.navigateToApp('settings'); - await createIndex('similar-index'); - await createIndex('similar-index-two'); + await createIndex('similar_index'); + await createIndex('similar_index_two'); - await PageObjects.settings.createIndexPattern('similar-index*', '@timestamp', true); + await PageObjects.settings.createIndexPattern('similar_index*', '@timestamp', true); await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); }); it('should navigate through rows with the same id but different indices correctly', async () => { - await PageObjects.discover.selectIndexPattern('similar-index*'); + await PageObjects.discover.selectIndexPattern('similar_index*'); await dataGrid.clickRowToggle(); const indexBeforePaginating = await testSubjects.getVisibleText( 'tableDocViewRow-_index-value' ); - expect(indexBeforePaginating).to.be('similar-index'); + expect(indexBeforePaginating).to.be('similar_index'); await testSubjects.click('pagination-button-next'); const indexAfterPaginating = await testSubjects.getVisibleText( 'tableDocViewRow-_index-value' ); - expect(indexAfterPaginating).to.be('similar-index-two'); + expect(indexAfterPaginating).to.be('similar_index_two'); }); }); } diff --git a/test/functional/config.base.js b/test/functional/config.base.js index f7f210aa7de32..c79ce9b60bd1e 100644 --- a/test/functional/config.base.js +++ b/test/functional/config.base.js @@ -209,7 +209,7 @@ export default async function ({ readConfigFile }) { cluster: [], indices: [ { - names: ['context-encoded-param'], + names: ['context_encoded_param'], privileges: ['read', 'view_index_metadata', 'manage', 'create_index', 'index'], field_security: { grant: ['*'], except: [] }, }, @@ -224,7 +224,7 @@ export default async function ({ readConfigFile }) { cluster: [], indices: [ { - names: ['similar-index'], + names: ['similar_index'], privileges: ['read', 'view_index_metadata', 'manage', 'create_index', 'index'], field_security: { grant: ['*'], except: [] }, }, @@ -239,7 +239,7 @@ export default async function ({ readConfigFile }) { cluster: [], indices: [ { - names: ['similar-index-two'], + names: ['similar_index_two'], privileges: ['read', 'view_index_metadata', 'manage', 'create_index', 'index'], field_security: { grant: ['*'], except: [] }, }, diff --git a/test/functional/fixtures/es_archiver/discover/data.json b/test/functional/fixtures/es_archiver/discover/data.json deleted file mode 100644 index 14a9f0559c6f3..0000000000000 --- a/test/functional/fixtures/es_archiver/discover/data.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "type": "doc", - "value": { - "id": "index-pattern:logstash-*", - "index": ".kibana", - "source": { - "coreMigrationVersion": "7.14.0", - "index-pattern": { - "fieldAttrs": "{\"referer\":{\"customLabel\":\"Referer custom\"}}", - "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@message\"}}},{\"name\":\"@tags\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@tags\"}}},{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"agent\"}}},{\"name\":\"bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"extension\"}}},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"headings\"}}},{\"name\":\"host\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"host\"}}},{\"name\":\"id\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"index\"}}},{\"name\":\"ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"links\"}}},{\"name\":\"machine.os\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"machine.os\"}}},{\"name\":\"machine.ram\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"esTypes\":[\"double\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nestedField.child\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"nested\":{\"path\":\"nestedField\"}}},{\"name\":\"phpmemory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:section\"}}},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:tag\"}}},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:description\"}}},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image\"}}},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:height\"}}},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:width\"}}},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:site_name\"}}},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:title\"}}},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:type\"}}},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:url\"}}},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:card\"}}},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:description\"}}},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:image\"}}},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:site\"}}},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:title\"}}},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.url\"}}},{\"name\":\"request\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"request\"}}},{\"name\":\"response\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"response\"}}},{\"name\":\"spaces\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"spaces\"}}},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"url\"}}},{\"name\":\"utc_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"xss\"}}}]", - "timeFieldName": "@timestamp", - "title": "logstash-*" - }, - "migrationVersion": { - "index-pattern": "7.11.0" - }, - "references": [ - ], - "type": "index-pattern" - }, - "type": "_doc" - } -} - -{ - "type": "doc", - "value": { - "id": "search:ab12e3c0-f231-11e6-9486-733b1ac9221a", - "index": ".kibana", - "source": { - "coreMigrationVersion": "7.14.0", - "migrationVersion": { - "search": "7.9.3" - }, - "references": [ - { - "id": "logstash-*", - "name": "kibanaSavedObjectMeta.searchSourceJSON.index", - "type": "index-pattern" - } - ], - "search": { - "columns": [ - "_source" - ], - "description": "A Saved Search Description", - "hits": 0, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"highlightAll\":true,\"filter\":[],\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" - }, - "sort": [ - [ - "@timestamp", - "desc" - ] - ], - "title": "A Saved Search", - "version": 1 - }, - "type": "search" - }, - "type": "_doc" - } -} \ No newline at end of file diff --git a/test/functional/fixtures/es_archiver/discover/mappings.json b/test/functional/fixtures/es_archiver/discover/mappings.json deleted file mode 100644 index 33bc746c84c8c..0000000000000 --- a/test/functional/fixtures/es_archiver/discover/mappings.json +++ /dev/null @@ -1,445 +0,0 @@ -{ - "type": "index", - "value": { - "aliases": { - ".kibana_$KIBANA_PACKAGE_VERSION": {}, - ".kibana": {} - }, - "index": ".kibana_$KIBANA_PACKAGE_VERSION_001", - "mappings": { - "_meta": { - "migrationMappingPropertyHashes": { - "application_usage_daily": "43b8830d5d0df85a6823d290885fc9fd", - "application_usage_totals": "3d1b76c39bfb2cc8296b024d73854724", - "application_usage_transactional": "3d1b76c39bfb2cc8296b024d73854724", - "config": "c63748b75f39d0c54de12d12c1ccbc20", - "core-usage-stats": "3d1b76c39bfb2cc8296b024d73854724", - "coreMigrationVersion": "2f4316de49999235636386fe51dc06c1", - "dashboard": "40554caf09725935e2c02e02563a2d07", - "index-pattern": "45915a1ad866812242df474eb0479052", - "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", - "legacy-url-alias": "6155300fd11a00e23d5cbaa39f0fce0a", - "migrationVersion": "4a1746014a75ade3a714e1db5763276f", - "namespace": "2f4316de49999235636386fe51dc06c1", - "namespaces": "2f4316de49999235636386fe51dc06c1", - "originId": "2f4316de49999235636386fe51dc06c1", - "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9", - "references": "7997cf5a56cc02bdc9c93361bde732b0", - "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", - "search": "db2c00e39b36f40930a3b9fc71c823e1", - "search-telemetry": "3d1b76c39bfb2cc8296b024d73854724", - "telemetry": "36a616f7026dfa617d6655df850fe16d", - "type": "2f4316de49999235636386fe51dc06c1", - "ui-counter": "0d409297dc5ebe1e3a1da691c6ee32e3", - "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3", - "updated_at": "00da57df13e94e9d98437d13ace4bfe0", - "url": "c7f66a0df8b1b52f17c28c4adb111105", - "usage-counters": "8cc260bdceffec4ffc3ad165c97dc1b4", - "visualization": "f819cf6636b75c9e76ba733a0c6ef355" - } - }, - "dynamic": "strict", - "properties": { - "application_usage_daily": { - "dynamic": "false", - "properties": { - "timestamp": { - "type": "date" - } - } - }, - "application_usage_totals": { - "dynamic": "false", - "type": "object" - }, - "application_usage_transactional": { - "dynamic": "false", - "type": "object" - }, - "config": { - "dynamic": "false", - "properties": { - "buildNum": { - "type": "keyword" - } - } - }, - "core-usage-stats": { - "dynamic": "false", - "type": "object" - }, - "coreMigrationVersion": { - "type": "keyword" - }, - "dashboard": { - "properties": { - "description": { - "type": "text" - }, - "hits": { - "doc_values": false, - "index": false, - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "index": false, - "type": "text" - } - } - }, - "optionsJSON": { - "index": false, - "type": "text" - }, - "panelsJSON": { - "index": false, - "type": "text" - }, - "refreshInterval": { - "properties": { - "display": { - "doc_values": false, - "index": false, - "type": "keyword" - }, - "pause": { - "doc_values": false, - "index": false, - "type": "boolean" - }, - "section": { - "doc_values": false, - "index": false, - "type": "integer" - }, - "value": { - "doc_values": false, - "index": false, - "type": "integer" - } - } - }, - "timeFrom": { - "doc_values": false, - "index": false, - "type": "keyword" - }, - "timeRestore": { - "doc_values": false, - "index": false, - "type": "boolean" - }, - "timeTo": { - "doc_values": false, - "index": false, - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "index-pattern": { - "dynamic": "false", - "properties": { - "title": { - "type": "text" - }, - "type": { - "type": "keyword" - } - } - }, - "kql-telemetry": { - "properties": { - "optInCount": { - "type": "long" - }, - "optOutCount": { - "type": "long" - } - } - }, - "legacy-url-alias": { - "dynamic": "false", - "properties": { - "disabled": { - "type": "boolean" - }, - "sourceId": { - "type": "keyword" - }, - "targetType": { - "type": "keyword" - } - } - }, - "migrationVersion": { - "dynamic": "true", - "properties": { - "index-pattern": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "search": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "namespace": { - "type": "keyword" - }, - "namespaces": { - "type": "keyword" - }, - "originId": { - "type": "keyword" - }, - "query": { - "properties": { - "description": { - "type": "text" - }, - "filters": { - "enabled": false, - "type": "object" - }, - "query": { - "properties": { - "language": { - "type": "keyword" - }, - "query": { - "index": false, - "type": "keyword" - } - } - }, - "timefilter": { - "enabled": false, - "type": "object" - }, - "title": { - "type": "text" - } - } - }, - "references": { - "properties": { - "id": { - "type": "keyword" - }, - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - }, - "type": "nested" - }, - "sample-data-telemetry": { - "properties": { - "installCount": { - "type": "long" - }, - "unInstallCount": { - "type": "long" - } - } - }, - "search": { - "properties": { - "columns": { - "doc_values": false, - "index": false, - "type": "keyword" - }, - "description": { - "type": "text" - }, - "grid": { - "enabled": false, - "type": "object" - }, - "hideChart": { - "doc_values": false, - "index": false, - "type": "boolean" - }, - "hits": { - "doc_values": false, - "index": false, - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "index": false, - "type": "text" - } - } - }, - "sort": { - "doc_values": false, - "index": false, - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "search-telemetry": { - "dynamic": "false", - "type": "object" - }, - "server": { - "dynamic": "false", - "type": "object" - }, - "telemetry": { - "properties": { - "allowChangingOptInStatus": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "lastReported": { - "type": "date" - }, - "lastVersionChecked": { - "type": "keyword" - }, - "reportFailureCount": { - "type": "integer" - }, - "reportFailureVersion": { - "type": "keyword" - }, - "sendUsageFrom": { - "type": "keyword" - }, - "userHasSeenNotice": { - "type": "boolean" - } - } - }, - "type": { - "type": "keyword" - }, - "ui-counter": { - "properties": { - "count": { - "type": "integer" - } - } - }, - "ui-metric": { - "properties": { - "count": { - "type": "integer" - } - } - }, - "updated_at": { - "type": "date" - }, - "url": { - "properties": { - "accessCount": { - "type": "long" - }, - "accessDate": { - "type": "date" - }, - "createDate": { - "type": "date" - }, - "url": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "usage-counters": { - "dynamic": "false", - "properties": { - "domainId": { - "type": "keyword" - } - } - }, - "visualization": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "index": false, - "type": "text" - } - } - }, - "savedSearchRefName": { - "doc_values": false, - "index": false, - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "index": false, - "type": "text" - }, - "version": { - "type": "integer" - }, - "visState": { - "index": false, - "type": "text" - } - } - } - } - }, - "settings": { - "index": { - "auto_expand_replicas": "0-1", - "number_of_replicas": "0", - "number_of_shards": "1", - "priority": "10", - "refresh_interval": "1s", - "routing_partition_size": "1" - } - } - } -} \ No newline at end of file diff --git a/test/functional/fixtures/kbn_archiver/discover/visual_regression.json b/test/functional/fixtures/kbn_archiver/discover/visual_regression.json new file mode 100644 index 0000000000000..c3782679b4809 --- /dev/null +++ b/test/functional/fixtures/kbn_archiver/discover/visual_regression.json @@ -0,0 +1,51 @@ +{ + "attributes": { + "fieldAttrs": "{\"referer\":{\"customLabel\":\"Referer custom\"}}", + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@message\"}}},{\"name\":\"@tags\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@tags\"}}},{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"agent\"}}},{\"name\":\"bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"extension\"}}},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"headings\"}}},{\"name\":\"host\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"host\"}}},{\"name\":\"id\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"index\"}}},{\"name\":\"ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"links\"}}},{\"name\":\"machine.os\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"machine.os\"}}},{\"name\":\"machine.ram\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"esTypes\":[\"double\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"nestedField.child\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"nested\":{\"path\":\"nestedField\"}}},{\"name\":\"phpmemory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:section\"}}},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:tag\"}}},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:description\"}}},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image\"}}},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:height\"}}},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:width\"}}},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:site_name\"}}},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:title\"}}},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:type\"}}},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:url\"}}},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:card\"}}},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:description\"}}},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:image\"}}},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:site\"}}},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:title\"}}},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.url\"}}},{\"name\":\"request\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"request\"}}},{\"name\":\"response\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"response\"}}},{\"name\":\"spaces\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"spaces\"}}},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"url\"}}},{\"name\":\"utc_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"esTypes\":[\"text\"],\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"xss\"}}}]", + "timeFieldName": "@timestamp", + "title": "logstash-*" + }, + "coreMigrationVersion": "8.4.0", + "id": "logstash-*", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "references": [], + "type": "index-pattern", + "version": "WzQsMV0=" +} + +{ + "attributes": { + "columns": [ + "_source" + ], + "description": "A Saved Search Description", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"highlightAll\":true,\"filter\":[],\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "title": "A Saved Search", + "version": 1 + }, + "coreMigrationVersion": "8.4.0", + "id": "ab12e3c0-f231-11e6-9486-733b1ac9221a", + "migrationVersion": { + "search": "8.0.0" + }, + "references": [ + { + "id": "logstash-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "search", + "version": "WzUsMV0=" +} diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index 17ab4e1b170f7..3a5c8e3d84db4 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -221,4 +221,10 @@ export class ConsolePageObject extends FtrService { return false; } } + + public async getResponseStatus() { + const statusBadge = await this.testSubjects.find('consoleResponseStatusBadge'); + const text = await statusBadge.getVisibleText(); + return text.replace(/[^\d.]+/, ''); + } } diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts index a035e05d9a0f1..7ff6bff172f58 100644 --- a/test/functional/page_objects/dashboard_page.ts +++ b/test/functional/page_objects/dashboard_page.ts @@ -42,6 +42,7 @@ export class DashboardPageObject extends FtrService { private readonly header = this.ctx.getPageObject('header'); private readonly visualize = this.ctx.getPageObject('visualize'); private readonly discover = this.ctx.getPageObject('discover'); + private readonly logstashIndex = this.config.get('esTestCluster.ccs') ? 'ftr-remote:logstash-*' : 'logstash-*'; @@ -605,6 +606,11 @@ export class DashboardPageObject extends FtrService { return panels.length; } + public async getAllPanels() { + this.log.debug('getAllPanels'); + return await this.testSubjects.findAll('embeddablePanel'); + } + public getTestVisualizations() { return [ { name: PIE_CHART_VIS_NAME, description: 'PieChart' }, diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 1e71c304165c5..5381d212598d9 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -143,6 +143,17 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'newsfeed.service.urlRoot (string)', 'telemetry.allowChangingOptInStatus (boolean)', 'telemetry.banner (boolean)', + 'telemetry.labels.branch (string)', + 'telemetry.labels.ciBuildId (string)', + 'telemetry.labels.ciBuildJobId (string)', + 'telemetry.labels.ciBuildNumber (number)', + 'telemetry.labels.ftrConfig (string)', + 'telemetry.labels.git_rev (string)', + 'telemetry.labels.isPr (boolean)', + 'telemetry.labels.journeyName (string)', + 'telemetry.labels.prId (string)', + 'telemetry.labels.testBuildId (string)', + 'telemetry.labels.testJobId (string)', 'telemetry.hidePrivacyStatement (boolean)', 'telemetry.optIn (boolean)', 'telemetry.sendUsageFrom (alternatives)', diff --git a/test/visual_regression/tests/discover/chart_visualization.ts b/test/visual_regression/tests/discover/chart_visualization.ts index 389a0a4b6a314..f8390064732b9 100644 --- a/test/visual_regression/tests/discover/chart_visualization.ts +++ b/test/visual_regression/tests/discover/chart_visualization.ts @@ -24,7 +24,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('discover', function describeIndexTests() { before(async function () { - await esArchiver.load('test/functional/fixtures/es_archiver/discover'); + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/discover/visual_regression' + ); // and load a set of makelogs data await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); @@ -33,8 +36,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.timePicker.setDefaultAbsoluteRange(); }); - after(function unloadMakelogs() { - return esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + after(async function unloadMakelogs() { + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + await kibanaServer.savedObjects.cleanStandardList(); }); async function refreshDiscover() { diff --git a/tsconfig.base.json b/tsconfig.base.json index 9946503830c70..c4a2d579dee9a 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -201,6 +201,8 @@ "@kbn/coverage-fixtures-plugin/*": ["test/common/fixtures/plugins/coverage/*"], "@kbn/newsfeed-fixtures-plugin": ["test/common/fixtures/plugins/newsfeed"], "@kbn/newsfeed-fixtures-plugin/*": ["test/common/fixtures/plugins/newsfeed/*"], + "@kbn/open-telemetry-instrumented-plugin": ["test/common/fixtures/plugins/otel_metrics"], + "@kbn/open-telemetry-instrumented-plugin/*": ["test/common/fixtures/plugins/otel_metrics/*"], "@kbn/kbn-tp-run-pipeline-plugin": ["test/interpreter_functional/plugins/kbn_tp_run_pipeline"], "@kbn/kbn-tp-run-pipeline-plugin/*": ["test/interpreter_functional/plugins/kbn_tp_run_pipeline/*"], "@kbn/app-link-test-plugin": ["test/plugin_functional/plugins/app_link_test"], diff --git a/x-pack/plugins/actions/README.md b/x-pack/plugins/actions/README.md index 3c5c459d5a780..c9b60be5e8c14 100644 --- a/x-pack/plugins/actions/README.md +++ b/x-pack/plugins/actions/README.md @@ -3,11 +3,11 @@ The Kibana actions plugin provides a framework to create executable actions. You can: - Register an action type and associate a JavaScript function to run when actions - are executed. + are generated. - Get a list of registered action types - Create an action from an action type and encrypted configuration object. - Get a list of actions that have been created. -- Execute an action, passing it a parameter object. +- Trigger an action, passing it a parameter object. - Perform CRUD operations on actions. --- @@ -81,13 +81,13 @@ Table of Contents **Action Type**: A programatically defined integration with another service, with an expected set of configuration and parameters properties, typically defined with a schema. Plugins can add new action types. -**Action**: A configuration object associated with an action type, that is ready to be executed. The configuration is persisted via Saved Objects, and some/none/all of the configuration properties can be stored encrypted. +**Action**: A configuration object associated with an action type, that is ready to run. The configuration is persisted via Saved Objects, and some/none/all of the configuration properties can be stored encrypted. ## Usage 1. Develop and register an action type (see [Action types -> Example](#example)). 2. Create an action by using the [RESTful API](#restful-api). -3. Use alerts to execute actions or execute manually (see [Firing actions](#firing-actions)). +3. Use alerting rules to generate actions or trigger them manually (see [Firing actions](#firing-actions)). ## Kibana Actions Configuration @@ -99,7 +99,8 @@ Built-In-Actions are configured using the _xpack.actions_ namespace under _kiban #### **allowedHosts** configuration -- You can use the string "*" in the **allowedHosts** configuration in place of a specific hostname to enable Kibana to target any URL, but keep in mind the potential to use such a feature to execute [SSRF](https://www.owasp.org/index.php/Server_Side_Request_Forgery) attacks from your server. +- You can use the string "*" in the **allowedHosts** configuration in place of a specific hostname to enable Kibana to target any URL, but keep in mind the potential to use such a feature to launch [SSRF](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) attacks from your server. + - The **allowedHosts** configuration applies to built-in action types (such as Slack and PagerDuty). While the _PagerDuty Action Type_ has been configured to support the service's Events API (at _https://events.pagerduty.com/v2/enqueue_, which you can read about in [Pagerduty's documentation](https://v2.developer.pagerduty.com/docs/events-api-v2)), the PagerDuty domain must still be included in the allowedHosts configuration before the action can be used. @@ -130,28 +131,28 @@ The following table describes the properties of the `options` object. | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | | id | Unique identifier for the action type. For convention, ids starting with `.` are reserved for built in action types. We recommend using a convention like `.mySpecialAction` for your action types. | string | | name | A user-friendly name for the action type. These will be displayed in dropdowns when chosing action types. | string | -| maxAttempts | The maximum number of times this action will attempt to execute when scheduled. | number | +| maxAttempts | The maximum number of times this action will attempt to run when scheduled. | number | | minimumLicenseRequired | The license required to use the action type. | string | | validate.params | When developing an action type, it needs to accept parameters to know what to do with the action. (Example `to`, `from`, `subject`, `body` of an email). See the current built-in email action type for an example of the state-of-the-art validation.

Technically, the value of this property should have a property named `validate()` which is a function that takes a params object to validate and returns a sanitized version of that object to pass to the execution function. Validation errors should be thrown from the `validate()` function and will be available as an error message | schema / validation function | | validate.config | Similar to params, a config may be required when creating an action (for example `host` and `port` for an email server). | schema / validation function | | validate.secrets | Similar to params, a secrets object may be required when creating an action (for example `user` and `password` for an email server). | schema / validation function | -| executor | This is where the code of an action type lives. This is a function gets called for executing an action from either alerting or manually by using the exposed function (see firing actions). For full details, see executor section below. | Function | +| executor | This is where the code of an action type lives. This is a function gets called for generating an action from either alerting or manually by using the exposed function (see firing actions). For full details, see executor section below. | Function | | renderParameterTemplates | Optionally define a function to provide custom rendering for this action type. | Function | **Important** - The config object is persisted in ElasticSearch and updated via the ElasticSearch update document API. This API allows "partial updates" - and this can cause issues with the encryption used on specified properties. So, a `validate()` function should return values for all configuration properties, so that partial updates do not occur. Setting property values to `null` rather than `undefined`, or not including a property in the config object, is all you need to do to ensure partial updates won't occur. ### Executor -This is the primary function for an action type. Whenever the action needs to execute, this function will perform the action. It receives a variety of parameters. The following table describes the properties that the executor receives. +This is the primary function for an action type. Whenever the action needs to run, this function will perform the action. It receives a variety of parameters. The following table describes the properties that the executor receives. **executor(options)** | Property | Description | | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| actionId | The action saved object id that the action type is executing for. | +| actionId | The action saved object id that the connector is generating. | | config | The action configuration. If you would like to validate the config before being passed to the executor, define `validate.config` within the action type. | | secrets | The decrypted secrets object given to an action. This comes from the action saved object that is partially or fully encrypted within the data store. If you would like to validate the secrets object before being passed to the executor, define `validate.secrets` within the action type. | -| params | Parameters for the execution. These will be given at execution time by either an alert or manually provided when calling the plugin provided execute function. | +| params | Parameters for the action. These will be given at run time by either an alert or manually provided when calling the plugin provided execute function. | | services.scopedClusterClient | Use this to do Elasticsearch queries on the cluster Kibana connects to. Serves the same purpose as the normal IClusterClient, but exposes an additional `asCurrentUser` method that doesn't use credentials of the Kibana internal user (as `asInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API instead. | | services.savedObjectsClient | This is an instance of the saved objects client. This provides the ability to do CRUD on any saved objects within the same space the alert lives in.

The scope of the saved objects client is tied to the user in context calling the execute API or the API key provided to the execute plugin function (only when security isenabled). | | services.log(tags, [data], [timestamp]) | Use this to create server logs. (This is the same function as server.log) | @@ -176,7 +177,7 @@ By providing the user's Request you'll receive an instance of the ActionsClient const actionsClient = server.plugins.actions.getActionsClientWithRequest(request); ``` -Once you have a scoped ActionsClient you can execute an action by caling either the `enqueueExecution` which will schedule the action to run later or the `execute` apis which will run it immediately and return the result respectively. +Once you have a scoped ActionsClient you can generate an action by calling either the `enqueueExecution` which will schedule the action to run later or the `execute` apis which will run it immediately and return the result respectively. ### actionsClient.enqueueExecution(options) @@ -191,7 +192,7 @@ The following table describes the properties of the `options` object. | Property | Description | Type | | -------- | ------------------------------------------------------------------------------------------------------ | ---------------- | -| id | The id of the action you want to execute. | string | +| id | The id of the action you want to run. | string | | params | The `params` value to give the action type executor. | object | | spaceId | The space id the action is within. | string | | apiKey | The Elasticsearch API key to use for context. (Note: only required and used when security is enabled). | string | @@ -225,7 +226,7 @@ The following table describes the properties of the `options` object. | Property | Description | Type | | -------- | ------------------------------------------------------------------------------------- | ---------------- | -| id | The id of the action you want to execute. | string | +| id | The id of the action you want to generate. | string | | params | The `params` value to give the action type executor. | object | | source | The source of the execution, either an HTTP request or a reference to a Saved Object. | object, optional | diff --git a/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts b/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts index cca2f8c045d3d..98093b685cab2 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts @@ -188,7 +188,9 @@ describe('execute()', () => { Object { "body": Array [ Object { - "index": Object {}, + "index": Object { + "op_type": "create", + }, }, Object { "jim": "bob", @@ -228,7 +230,9 @@ describe('execute()', () => { Object { "body": Array [ Object { - "index": Object {}, + "index": Object { + "op_type": "create", + }, }, Object { "jimbob": "jr", @@ -262,7 +266,9 @@ describe('execute()', () => { Object { "body": Array [ Object { - "index": Object {}, + "index": Object { + "op_type": "create", + }, }, Object { "jim": "bob", @@ -295,13 +301,17 @@ describe('execute()', () => { Object { "body": Array [ Object { - "index": Object {}, + "index": Object { + "op_type": "create", + }, }, Object { "a": 1, }, Object { - "index": Object {}, + "index": Object { + "op_type": "create", + }, }, Object { "b": 2, diff --git a/x-pack/plugins/actions/server/builtin_action_types/es_index.ts b/x-pack/plugins/actions/server/builtin_action_types/es_index.ts index 2a2ca0504d3ac..a0ddea9913bef 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/es_index.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/es_index.ts @@ -89,7 +89,7 @@ async function executor( document[timeField] = new Date(); } - bulkBody.push({ index: {} }); + bulkBody.push({ index: { op_type: 'create' } }); bulkBody.push(document); } diff --git a/x-pack/plugins/actions/server/lib/mustache_renderer.test.ts b/x-pack/plugins/actions/server/lib/mustache_renderer.test.ts index a72e0fd54bd17..2dff9bac3eddf 100644 --- a/x-pack/plugins/actions/server/lib/mustache_renderer.test.ts +++ b/x-pack/plugins/actions/server/lib/mustache_renderer.test.ts @@ -28,6 +28,7 @@ const variables = { st: '*', ul: '_', st_lt: '*<', + vl: '|', }; describe('mustache_renderer', () => { @@ -77,6 +78,7 @@ describe('mustache_renderer', () => { expect(renderMustacheString('{{bs}}', variables, 'markdown')).toBe('\\' + variables.bs); expect(renderMustacheString('{{st}}', variables, 'markdown')).toBe('\\' + variables.st); expect(renderMustacheString('{{ul}}', variables, 'markdown')).toBe('\\' + variables.ul); + expect(renderMustacheString('{{vl}}', variables, 'markdown')).toBe('\\' + variables.vl); }); it('handles triple escapes', () => { diff --git a/x-pack/plugins/actions/server/lib/mustache_renderer.ts b/x-pack/plugins/actions/server/lib/mustache_renderer.ts index 1e7f2dd3ab644..24c18f7654d4f 100644 --- a/x-pack/plugins/actions/server/lib/mustache_renderer.ts +++ b/x-pack/plugins/actions/server/lib/mustache_renderer.ts @@ -123,6 +123,7 @@ function escapeMarkdown(value: unknown): string { return `${value}` .replace(/\\/g, '\\\\') + .replace(/\|/g, '\\|') .replace(/`/g, '\\`') .replace(/\*/g, '\\*') .replace(/_/g, '\\_') diff --git a/x-pack/plugins/aiops/public/application/services/timefilter_refresh_service.ts b/x-pack/plugins/aiops/public/application/services/timefilter_refresh_service.ts index 20eab7968fefc..05edd75d599bf 100644 --- a/x-pack/plugins/aiops/public/application/services/timefilter_refresh_service.ts +++ b/x-pack/plugins/aiops/public/application/services/timefilter_refresh_service.ts @@ -12,4 +12,4 @@ export interface Refresh { timeRange?: { start: string; end: string }; } -export const aiOpsRefresh$ = new Subject(); +export const aiopsRefresh$ = new Subject(); diff --git a/x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx b/x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx index 00e74bc7db618..931993a354d6c 100644 --- a/x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx +++ b/x-pack/plugins/aiops/public/components/date_picker_wrapper/date_picker_wrapper.tsx @@ -15,7 +15,7 @@ import { TimeHistoryContract, UI_SETTINGS } from '@kbn/data-plugin/public'; import { useUrlState } from '../../hooks/url_state'; import { useAiOpsKibana } from '../../kibana_context'; -import { aiOpsRefresh$ } from '../../application/services/timefilter_refresh_service'; +import { aiopsRefresh$ } from '../../application/services/timefilter_refresh_service'; interface TimePickerQuickRange { from: string; @@ -47,7 +47,7 @@ function getRecentlyUsedRangesFactory(timeHistory: TimeHistoryContract) { } function updateLastRefresh(timeRange: OnRefreshProps) { - aiOpsRefresh$.next({ lastRefresh: Date.now(), timeRange }); + aiopsRefresh$.next({ lastRefresh: Date.now(), timeRange }); } export const DatePickerWrapper: FC = () => { diff --git a/x-pack/plugins/aiops/public/components/document_count_content/document_count_chart/document_count_chart.tsx b/x-pack/plugins/aiops/public/components/document_count_content/document_count_chart/document_count_chart.tsx index f58730544896b..308e91f47506a 100644 --- a/x-pack/plugins/aiops/public/components/document_count_content/document_count_chart/document_count_chart.tsx +++ b/x-pack/plugins/aiops/public/components/document_count_content/document_count_chart/document_count_chart.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import React, { FC, useCallback, useMemo } from 'react'; -import { i18n } from '@kbn/i18n'; +import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; +import moment from 'moment'; + import { Axis, BarSeries, @@ -19,9 +20,14 @@ import { XYChartElementEvent, XYBrushEvent, } from '@elastic/charts'; -import moment from 'moment'; + +import { i18n } from '@kbn/i18n'; import { IUiSettingsClient } from '@kbn/core/public'; +import { DualBrush, DualBrushAnnotation } from '@kbn/aiops-components'; +import { getWindowParameters } from '@kbn/aiops-utils'; +import type { WindowParameters } from '@kbn/aiops-utils'; import { MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; + import { useAiOpsKibana } from '../../../kibana_context'; export interface DocumentCountChartPoint { @@ -29,16 +35,22 @@ export interface DocumentCountChartPoint { value: number; } -interface Props { +interface DocumentCountChartProps { + brushSelectionUpdateHandler: (d: WindowParameters) => void; width?: number; chartPoints: DocumentCountChartPoint[]; timeRangeEarliest: number; timeRangeLatest: number; - interval?: number; + interval: number; } const SPEC_ID = 'document_count'; +enum VIEW_MODE { + ZOOM = 'zoom', + BRUSH = 'brush', +} + function getTimezone(uiSettings: IUiSettingsClient) { if (uiSettings.isDefault('dateFormat:tz')) { const detectedTimezone = moment.tz.guess(); @@ -49,7 +61,8 @@ function getTimezone(uiSettings: IUiSettingsClient) { } } -export const DocumentCountChart: FC = ({ +export const DocumentCountChart: FC = ({ + brushSelectionUpdateHandler, width, chartPoints, timeRangeEarliest, @@ -70,6 +83,9 @@ export const DocumentCountChart: FC = ({ defaultMessage: 'document count', }); + // TODO Let user choose between ZOOM and BRUSH mode. + const [viewMode] = useState(VIEW_MODE.BRUSH); + const xDomain = { min: timeRangeEarliest, max: timeRangeLatest, @@ -117,46 +133,120 @@ export const DocumentCountChart: FC = ({ from: startRange, to: startRange + interval, }; - timefilterUpdateHandler(range); + + if (viewMode === VIEW_MODE.ZOOM) { + timefilterUpdateHandler(range); + } else { + if ( + typeof startRange === 'number' && + originalWindowParameters === undefined && + windowParameters === undefined && + adjustedChartPoints !== undefined + ) { + const wp = getWindowParameters( + startRange + interval / 2, + xDomain.min, + xDomain.max + interval + ); + setOriginalWindowParameters(wp); + setWindowParameters(wp); + brushSelectionUpdateHandler(wp); + } + } }; const timeZone = getTimezone(uiSettings); + const [originalWindowParameters, setOriginalWindowParameters] = useState< + WindowParameters | undefined + >(); + const [windowParameters, setWindowParameters] = useState(); + + function onWindowParametersChange(wp: WindowParameters) { + setWindowParameters(wp); + brushSelectionUpdateHandler(wp); + } + + const [mlBrushWidth, setMlBrushWidth] = useState(); + const [mlBrushMarginLeft, setMlBrushMarginLeft] = useState(); + + useEffect(() => { + if (viewMode !== VIEW_MODE.BRUSH) { + setOriginalWindowParameters(undefined); + setWindowParameters(undefined); + } + }, [viewMode]); + + const isBrushVisible = + originalWindowParameters && mlBrushMarginLeft && mlBrushWidth && mlBrushWidth > 0; + return ( -

- - - xAxisFormatter.convert(value)} - timeAxisLayerCount={useLegacyTimeAxis ? 0 : 2} - style={useLegacyTimeAxis ? {} : MULTILAYER_TIME_AXIS_STYLE} - /> - - - -
+ <> + {isBrushVisible && ( +
+ +
+ )} +
+ + { + setMlBrushMarginLeft(projection.left); + setMlBrushWidth(projection.width); + }} + theme={chartTheme} + baseTheme={chartBaseTheme} + /> + xAxisFormatter.convert(value)} + timeAxisLayerCount={useLegacyTimeAxis ? 0 : 2} + style={useLegacyTimeAxis ? {} : MULTILAYER_TIME_AXIS_STYLE} + /> + + + {windowParameters && ( + <> + + + + )} + +
+ ); }; diff --git a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx index db55d6bd718ec..0843d1d5f2736 100644 --- a/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/aiops/public/components/document_count_content/document_count_content/document_count_content.tsx @@ -5,16 +5,24 @@ * 2.0. */ import React, { FC } from 'react'; + +import { WindowParameters } from '@kbn/aiops-utils'; + import { DocumentCountChart, DocumentCountChartPoint } from '../document_count_chart'; import { TotalCountHeader } from '../total_count_header'; import { DocumentCountStats } from '../../../get_document_stats'; -export interface Props { +export interface DocumentCountContentProps { + brushSelectionUpdateHandler: (d: WindowParameters) => void; documentCountStats?: DocumentCountStats; totalCount: number; } -export const DocumentCountContent: FC = ({ documentCountStats, totalCount }) => { +export const DocumentCountContent: FC = ({ + brushSelectionUpdateHandler, + documentCountStats, + totalCount, +}) => { if (documentCountStats === undefined) { return totalCount !== undefined ? : null; } @@ -32,12 +40,15 @@ export const DocumentCountContent: FC = ({ documentCountStats, totalCount return ( <> - + {documentCountStats.interval !== undefined && ( + + )} ); }; diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes.tsx index 468d543ddeefd..e0d135522a30c 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes.tsx @@ -7,18 +7,6 @@ import React, { useEffect, FC } from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, - EuiPageBody, - EuiPageContentBody, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiSpacer, - EuiTitle, -} from '@elastic/eui'; - import type { DataView } from '@kbn/data-views-plugin/public'; import { ProgressControls } from '@kbn/aiops-components'; import { useFetchStream } from '@kbn/aiops-utils'; @@ -28,44 +16,38 @@ import { useAiOpsKibana } from '../../kibana_context'; import { initialState, streamReducer } from '../../../common/api/stream_reducer'; import type { ApiExplainLogRateSpikes } from '../../../common/api'; import { SpikeAnalysisTable } from '../spike_analysis_table'; -import { FullTimeRangeSelector } from '../full_time_range_selector'; -import { DocumentCountContent } from '../document_count_content/document_count_content'; -import { DatePickerWrapper } from '../date_picker_wrapper'; -import { useData } from '../../hooks/use_data'; -import { useUrlState } from '../../hooks/url_state'; /** * ExplainLogRateSpikes props require a data view. */ -export interface ExplainLogRateSpikesProps { +interface ExplainLogRateSpikesProps { /** The data view to analyze. */ dataView: DataView; + /** Start timestamp filter */ + earliest: number; + /** End timestamp filter */ + latest: number; /** Window parameters for the analysis */ windowParameters: WindowParameters; } export const ExplainLogRateSpikes: FC = ({ dataView, + earliest, + latest, windowParameters, }) => { const { services } = useAiOpsKibana(); const basePath = services.http?.basePath.get() ?? ''; - const [globalState, setGlobalState] = useUrlState('_g'); - - const { docStats, timefilter } = useData(dataView, setGlobalState); - const { cancel, start, data, isRunning, error } = useFetchStream< ApiExplainLogRateSpikes, typeof basePath >( `${basePath}/internal/aiops/explain_log_rate_spikes`, { - // TODO Consider actual user selected time ranges. - // Since we already receive window parameters here, - // we just set a maximum time range of 1970-2038 here. - start: 0, - end: 2147483647000, + start: earliest, + end: latest, // TODO Consider an optional Kuery. kuery: '', // TODO Handle data view without time fields. @@ -76,100 +58,23 @@ export const ExplainLogRateSpikes: FC = ({ { reducer: streamReducer, initialState } ); - useEffect(() => { - if (globalState?.time !== undefined) { - timefilter.setTime({ - from: globalState.time.from, - to: globalState.time.to, - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [JSON.stringify(globalState?.time), timefilter]); - - useEffect(() => { - if (globalState?.refreshInterval !== undefined) { - timefilter.setRefreshInterval(globalState.refreshInterval); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [JSON.stringify(globalState?.refreshInterval), timefilter]); - useEffect(() => { start(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - if (!dataView || !timefilter) return null; - return ( <> - - - - - -
- -

{dataView.title}

-
-
-
- - - {dataView.timeFieldName !== undefined && ( - - - - )} - - - - -
-
-
- - - - - {docStats?.totalCount !== undefined && ( - - - - )} - - - - {data?.changePoints ? ( - - - - ) : null} - - -
+ + {data?.changePoints ? ( + + ) : null} ); }; diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_wrapper.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_wrapper.tsx index 1b72aac836c18..8c254be451515 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_wrapper.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_wrapper.tsx @@ -5,11 +5,27 @@ * 2.0. */ -import React, { FC, useCallback } from 'react'; +import React, { FC, useCallback, useEffect, useState } from 'react'; import { parse, stringify } from 'query-string'; import { isEqual } from 'lodash'; import { encode } from 'rison-node'; import { useHistory, useLocation } from 'react-router-dom'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPageBody, + EuiPageContentBody, + EuiPageContentHeader, + EuiPageContentHeaderSection, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; + +import type { WindowParameters } from '@kbn/aiops-utils'; +import type { DataView } from '@kbn/data-views-plugin/public'; + import { Accessor, Dictionary, @@ -19,10 +35,51 @@ import { getNestedProperty, SetUrlState, } from '../../hooks/url_state'; +import { useData } from '../../hooks/use_data'; +import { useUrlState } from '../../hooks/url_state'; + +import { FullTimeRangeSelector } from '../full_time_range_selector'; +import { DocumentCountContent } from '../document_count_content/document_count_content'; +import { DatePickerWrapper } from '../date_picker_wrapper'; + +import { ExplainLogRateSpikes } from './explain_log_rate_spikes'; + +export interface ExplainLogRateSpikesWrapperProps { + /** The data view to analyze. */ + dataView: DataView; +} -import { ExplainLogRateSpikes, ExplainLogRateSpikesProps } from './explain_log_rate_spikes'; +export const ExplainLogRateSpikesWrapper: FC = ({ dataView }) => { + const [globalState, setGlobalState] = useUrlState('_g'); + + const { docStats, timefilter } = useData(dataView, setGlobalState); + const [windowParameters, setWindowParameters] = useState(); + + const activeBounds = timefilter.getActiveBounds(); + let earliest: number | undefined; + let latest: number | undefined; + if (activeBounds !== undefined) { + earliest = activeBounds.min?.valueOf(); + latest = activeBounds.max?.valueOf(); + } + + useEffect(() => { + if (globalState?.time !== undefined) { + timefilter.setTime({ + from: globalState.time.from, + to: globalState.time.to, + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [JSON.stringify(globalState?.time), timefilter]); + + useEffect(() => { + if (globalState?.refreshInterval !== undefined) { + timefilter.setRefreshInterval(globalState.refreshInterval); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [JSON.stringify(globalState?.refreshInterval), timefilter]); -export const ExplainLogRateSpikesWrapper: FC = (props) => { const history = useHistory(); const { search: urlSearchString } = useLocation(); @@ -88,9 +145,65 @@ export const ExplainLogRateSpikesWrapper: FC = (props [history, urlSearchString] ); + if (!dataView || !timefilter) return null; + return ( - {' '} + + + + + +
+ +

{dataView.title}

+
+
+
+ + + {dataView.timeFieldName !== undefined && ( + + + + )} + + + + +
+
+
+ + + {docStats?.totalCount !== undefined && ( + + )} + + {earliest !== undefined && latest !== undefined && windowParameters !== undefined && ( + + )} + +
); }; diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/index.ts b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/index.ts index 4666380c7bd61..4c344313209e4 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/index.ts +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -export type { ExplainLogRateSpikesProps } from './explain_log_rate_spikes'; +export type { ExplainLogRateSpikesWrapperProps } from './explain_log_rate_spikes_wrapper'; import { ExplainLogRateSpikesWrapper } from './explain_log_rate_spikes_wrapper'; // required for dynamic import using React.lazy() diff --git a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx index 3910bd8cc5a02..9e125f4d47305 100644 --- a/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx +++ b/x-pack/plugins/aiops/public/components/spike_analysis_table/spike_analysis_table.tsx @@ -117,6 +117,7 @@ export const SpikeAnalysisTable: FC = ({ changePointData, error, loading return ( { // This uses a context to be able to maintain only one instance // of the url state. It gets passed down with `UrlStateProvider` // and can be used via `useUrlState`. -export const aiOpsUrlStateStore = createContext({ +export const aiopsUrlStateStore = createContext({ searchString: '', setUrlState: () => {}, }); -export const { Provider } = aiOpsUrlStateStore; +export const { Provider } = aiopsUrlStateStore; export const useUrlState = (accessor: Accessor) => { - const { searchString, setUrlState: setUrlStateContext } = useContext(aiOpsUrlStateStore); + const { searchString, setUrlState: setUrlStateContext } = useContext(aiopsUrlStateStore); const urlState = useMemo(() => { const fullUrlState = parseUrlState(searchString); diff --git a/x-pack/plugins/aiops/public/hooks/use_data.ts b/x-pack/plugins/aiops/public/hooks/use_data.ts index b3cadd2d44f79..85be019d14e50 100644 --- a/x-pack/plugins/aiops/public/hooks/use_data.ts +++ b/x-pack/plugins/aiops/public/hooks/use_data.ts @@ -11,7 +11,7 @@ import { merge } from 'rxjs'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; import { useAiOpsKibana } from '../kibana_context'; import { useTimefilter } from './use_time_filter'; -import { aiOpsRefresh$ } from '../application/services/timefilter_refresh_service'; +import { aiopsRefresh$ } from '../application/services/timefilter_refresh_service'; import { TimeBuckets } from '../../common/time_buckets'; import { useDocumentCountStats } from './use_document_count_stats'; import { Dictionary } from './url_state'; @@ -80,7 +80,7 @@ export const useData = ( const timeUpdateSubscription = merge( timefilter.getTimeUpdate$(), timefilter.getAutoRefreshFetch$(), - aiOpsRefresh$ + aiopsRefresh$ ).subscribe(() => { if (onUpdate) { onUpdate({ diff --git a/x-pack/plugins/aiops/public/hooks/use_storage.ts b/x-pack/plugins/aiops/public/hooks/use_storage.ts index 7459560d127bf..ef8bf85f2507d 100644 --- a/x-pack/plugins/aiops/public/hooks/use_storage.ts +++ b/x-pack/plugins/aiops/public/hooks/use_storage.ts @@ -8,7 +8,7 @@ import { useCallback, useState } from 'react'; import { useAiOpsKibana } from '../kibana_context'; -export const AIOPS_FROZEN_TIER_PREFERENCE = 'aiOps.frozenDataTierPreference'; +export const AIOPS_FROZEN_TIER_PREFERENCE = 'aiop.frozenDataTierPreference'; export type AiOps = Partial<{ [AIOPS_FROZEN_TIER_PREFERENCE]: 'exclude_frozen' | 'include_frozen'; diff --git a/x-pack/plugins/aiops/public/index.ts b/x-pack/plugins/aiops/public/index.ts index 26166e7ca104d..5810d38d57308 100755 --- a/x-pack/plugins/aiops/public/index.ts +++ b/x-pack/plugins/aiops/public/index.ts @@ -13,6 +13,5 @@ export function plugin() { return new AiopsPlugin(); } -export type { ExplainLogRateSpikesProps } from './components/explain_log_rate_spikes'; export { ExplainLogRateSpikes } from './shared_lazy_components'; export type { AiopsPluginSetup, AiopsPluginStart } from './types'; diff --git a/x-pack/plugins/aiops/public/shared_lazy_components.tsx b/x-pack/plugins/aiops/public/shared_lazy_components.tsx index 95dcdc50ae2ac..d967a6434d83c 100644 --- a/x-pack/plugins/aiops/public/shared_lazy_components.tsx +++ b/x-pack/plugins/aiops/public/shared_lazy_components.tsx @@ -9,7 +9,7 @@ import React, { FC, Suspense } from 'react'; import { EuiErrorBoundary, EuiLoadingContent } from '@elastic/eui'; -import type { ExplainLogRateSpikesProps } from './components/explain_log_rate_spikes'; +import type { ExplainLogRateSpikesWrapperProps } from './components/explain_log_rate_spikes'; const ExplainLogRateSpikesWrapperLazy = React.lazy( () => import('./components/explain_log_rate_spikes') @@ -22,10 +22,10 @@ const LazyWrapper: FC = ({ children }) => ( ); /** - * Lazy-wrapped ExplainLogRateSpikes React component - * @param {ExplainLogRateSpikesProps} props - properties specifying the data on which to run the analysis. + * Lazy-wrapped ExplainLogRateSpikesWrapper React component + * @param {ExplainLogRateSpikesWrapperProps} props - properties specifying the data on which to run the analysis. */ -export const ExplainLogRateSpikes: FC = (props) => ( +export const ExplainLogRateSpikes: FC = (props) => ( diff --git a/x-pack/plugins/alerting/server/alert/create_alert_factory.test.ts b/x-pack/plugins/alerting/server/alert/create_alert_factory.test.ts index f8d61e64c9eaf..c9505d5f838e2 100644 --- a/x-pack/plugins/alerting/server/alert/create_alert_factory.test.ts +++ b/x-pack/plugins/alerting/server/alert/create_alert_factory.test.ts @@ -9,10 +9,10 @@ import sinon from 'sinon'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { Alert } from './alert'; import { createAlertFactory } from './create_alert_factory'; -import { getRecoveredAlerts } from '../lib'; +import { processAlerts } from '../lib'; jest.mock('../lib', () => ({ - getRecoveredAlerts: jest.fn(), + processAlerts: jest.fn(), })); let clock: sinon.SinonFakeTimers; @@ -37,6 +37,7 @@ describe('createAlertFactory()', () => { "state": Object {}, } `); + // @ts-expect-error expect(result.getId()).toEqual('1'); }); @@ -108,16 +109,18 @@ describe('createAlertFactory()', () => { }); test('returns recovered alerts when setsRecoveryContext is true', () => { - (getRecoveredAlerts as jest.Mock).mockReturnValueOnce({ - z: { - id: 'z', - state: { foo: true }, - meta: { lastScheduledActions: { group: 'default', date: new Date() } }, - }, - y: { - id: 'y', - state: { foo: true }, - meta: { lastScheduledActions: { group: 'default', date: new Date() } }, + (processAlerts as jest.Mock).mockReturnValueOnce({ + recoveredAlerts: { + z: { + id: 'z', + state: { foo: true }, + meta: { lastScheduledActions: { group: 'default', date: new Date() } }, + }, + y: { + id: 'y', + state: { foo: true }, + meta: { lastScheduledActions: { group: 'default', date: new Date() } }, + }, }, }); const alertFactory = createAlertFactory({ @@ -142,7 +145,7 @@ describe('createAlertFactory()', () => { }); test('returns empty array if no recovered alerts', () => { - (getRecoveredAlerts as jest.Mock).mockReturnValueOnce({}); + (processAlerts as jest.Mock).mockReturnValueOnce({ recoveredAlerts: {} }); const alertFactory = createAlertFactory({ alerts: {}, logger, @@ -163,8 +166,8 @@ describe('createAlertFactory()', () => { expect(recoveredAlerts.length).toEqual(0); }); - test('returns empty array if getRecoveredAlerts returns null', () => { - (getRecoveredAlerts as jest.Mock).mockReturnValueOnce(null); + test('returns empty array if recovered alerts are null', () => { + (processAlerts as jest.Mock).mockReturnValueOnce({ recoveredAlerts: null }); const alertFactory = createAlertFactory({ alerts: {}, logger, diff --git a/x-pack/plugins/alerting/server/alert/create_alert_factory.ts b/x-pack/plugins/alerting/server/alert/create_alert_factory.ts index 9528273fb28db..5a9dad5cdada8 100644 --- a/x-pack/plugins/alerting/server/alert/create_alert_factory.ts +++ b/x-pack/plugins/alerting/server/alert/create_alert_factory.ts @@ -6,52 +6,48 @@ */ import { Logger } from '@kbn/core/server'; +import { cloneDeep } from 'lodash'; import { AlertInstanceContext, AlertInstanceState } from '../types'; -import { Alert } from './alert'; -import { getRecoveredAlerts } from '../lib'; +import { Alert, PublicAlert } from './alert'; +import { processAlerts } from '../lib'; export interface AlertFactoryDoneUtils< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext, + State extends AlertInstanceState, + Context extends AlertInstanceContext, ActionGroupIds extends string > { - getRecoveredAlerts: () => Array>; + getRecoveredAlerts: () => Array>; } export interface CreateAlertFactoryOpts< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext, - ActionGroupIds extends string + State extends AlertInstanceState, + Context extends AlertInstanceContext > { - alerts: Record>; + alerts: Record>; logger: Logger; canSetRecoveryContext?: boolean; } export function createAlertFactory< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext, + State extends AlertInstanceState, + Context extends AlertInstanceContext, ActionGroupIds extends string ->({ - alerts, - logger, - canSetRecoveryContext = false, -}: CreateAlertFactoryOpts) { +>({ alerts, logger, canSetRecoveryContext = false }: CreateAlertFactoryOpts) { // Keep track of which alerts we started with so we can determine which have recovered - const initialAlertIds = new Set(Object.keys(alerts)); + const originalAlerts = cloneDeep(alerts); let isDone = false; return { - create: (id: string): Alert => { + create: (id: string): PublicAlert => { if (isDone) { throw new Error(`Can't create new alerts after calling done() in AlertsFactory.`); } if (!alerts[id]) { - alerts[id] = new Alert(id); + alerts[id] = new Alert(id); } return alerts[id]; }, - done: (): AlertFactoryDoneUtils => { + done: (): AlertFactoryDoneUtils => { isDone = true; return { getRecoveredAlerts: () => { @@ -62,8 +58,11 @@ export function createAlertFactory< return []; } - const recoveredAlerts = getRecoveredAlerts(alerts, initialAlertIds); - return Object.keys(recoveredAlerts ?? []).map( + const { recoveredAlerts } = processAlerts( + alerts, + originalAlerts + ); + return Object.keys(recoveredAlerts ?? {}).map( (alertId: string) => recoveredAlerts[alertId] ); }, diff --git a/x-pack/plugins/alerting/server/lib/get_recovered_alerts.test.ts b/x-pack/plugins/alerting/server/lib/get_recovered_alerts.test.ts deleted file mode 100644 index b984b04fc65d4..0000000000000 --- a/x-pack/plugins/alerting/server/lib/get_recovered_alerts.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getRecoveredAlerts } from './get_recovered_alerts'; -import { Alert } from '../alert'; -import { AlertInstanceState, AlertInstanceContext, DefaultActionGroupId } from '../types'; - -describe('getRecoveredAlerts', () => { - test('considers alert recovered if it has no scheduled actions', () => { - const alert1 = new Alert('1'); - alert1.scheduleActions('default', { foo: '1' }); - - const alert2 = new Alert('2'); - alert2.setContext({ foo: '2' }); - const alerts = { - '1': alert1, - '2': alert2, - }; - - expect(getRecoveredAlerts(alerts, new Set(['1', '2']))).toEqual({ - '2': alert2, - }); - }); - - test('does not consider alert recovered if it has no actions but was not in original alerts list', () => { - const alert1 = new Alert('1'); - alert1.scheduleActions('default', { foo: '1' }); - const alert2 = new Alert('2'); - const alerts = { - '1': alert1, - '2': alert2, - }; - - expect(getRecoveredAlerts(alerts, new Set(['1']))).toEqual({}); - }); -}); diff --git a/x-pack/plugins/alerting/server/lib/get_recovered_alerts.ts b/x-pack/plugins/alerting/server/lib/get_recovered_alerts.ts deleted file mode 100644 index f389f56a813d0..0000000000000 --- a/x-pack/plugins/alerting/server/lib/get_recovered_alerts.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { Dictionary, pickBy } from 'lodash'; -import { Alert } from '../alert'; -import { AlertInstanceState, AlertInstanceContext } from '../types'; - -export function getRecoveredAlerts< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext, - RecoveryActionGroupId extends string ->( - alerts: Record>, - originalAlertIds: Set -): Dictionary> { - return pickBy( - alerts, - (alert: Alert, id) => - !alert.hasScheduledActions() && originalAlertIds.has(id) - ); -} diff --git a/x-pack/plugins/alerting/server/lib/index.ts b/x-pack/plugins/alerting/server/lib/index.ts index 1d65497b15212..d221c2251d386 100644 --- a/x-pack/plugins/alerting/server/lib/index.ts +++ b/x-pack/plugins/alerting/server/lib/index.ts @@ -25,7 +25,7 @@ export { ruleExecutionStatusToRaw, ruleExecutionStatusFromRaw, } from './rule_execution_status'; -export { getRecoveredAlerts } from './get_recovered_alerts'; +export { processAlerts } from './process_alerts'; export { createWrappedScopedClusterClientFactory } from './wrap_scoped_cluster_client'; export { isRuleSnoozed, getRuleSnoozeEndTime } from './is_rule_snoozed'; export { convertRuleIdsToKueryNode } from './convert_rule_ids_to_kuery_node'; diff --git a/x-pack/plugins/alerting/server/lib/process_alerts.test.ts b/x-pack/plugins/alerting/server/lib/process_alerts.test.ts new file mode 100644 index 0000000000000..a242ac471ad11 --- /dev/null +++ b/x-pack/plugins/alerting/server/lib/process_alerts.test.ts @@ -0,0 +1,413 @@ +/* + * Copyright 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 sinon from 'sinon'; +import { cloneDeep } from 'lodash'; +import { processAlerts } from './process_alerts'; +import { Alert } from '../alert'; +import { DefaultActionGroupId } from '../types'; + +describe('processAlerts', () => { + let clock: sinon.SinonFakeTimers; + + beforeAll(() => { + clock = sinon.useFakeTimers(); + }); + + beforeEach(() => { + clock.reset(); + }); + + afterAll(() => clock.restore()); + + describe('newAlerts', () => { + test('considers alert new if it has scheduled actions and its id is not in originalAlertIds list', () => { + const newAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const existingAlert1 = new Alert<{}, {}, DefaultActionGroupId>('2'); + const existingAlert2 = new Alert<{}, {}, DefaultActionGroupId>('3'); + + const originalAlerts = { + '2': existingAlert1, + '3': existingAlert2, + }; + + const updatedAlerts = { + ...cloneDeep(originalAlerts), + '1': newAlert, + }; + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + updatedAlerts['2'].scheduleActions('default', { foo: '1' }); + updatedAlerts['3'].scheduleActions('default', { foo: '2' }); + + // @ts-expect-error + const { newAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(newAlerts).toEqual({ '1': newAlert }); + }); + + test('sets start time in new alert state', () => { + const newAlert1 = new Alert<{}, {}, DefaultActionGroupId>('1'); + const newAlert2 = new Alert<{}, {}, DefaultActionGroupId>('2'); + const existingAlert1 = new Alert<{}, {}, DefaultActionGroupId>('3'); + const existingAlert2 = new Alert<{}, {}, DefaultActionGroupId>('4'); + + const originalAlerts = { + '3': existingAlert1, + '4': existingAlert2, + }; + + const updatedAlerts = { + ...cloneDeep(originalAlerts), + '1': newAlert1, + '2': newAlert2, + }; + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + updatedAlerts['2'].scheduleActions('default', { foo: '1' }); + updatedAlerts['3'].scheduleActions('default', { foo: '1' }); + updatedAlerts['4'].scheduleActions('default', { foo: '2' }); + + expect(newAlert1.getState()).toStrictEqual({}); + expect(newAlert2.getState()).toStrictEqual({}); + + // @ts-expect-error + const { newAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(newAlerts).toEqual({ '1': newAlert1, '2': newAlert2 }); + + const newAlert1State = newAlerts['1'].getState(); + const newAlert2State = newAlerts['2'].getState(); + + // @ts-expect-error + expect(newAlert1State.start).toEqual('1970-01-01T00:00:00.000Z'); + // @ts-expect-error + expect(newAlert2State.start).toEqual('1970-01-01T00:00:00.000Z'); + + // @ts-expect-error + expect(newAlert1State.duration).toEqual('0'); + // @ts-expect-error + expect(newAlert2State.duration).toEqual('0'); + + // @ts-expect-error + expect(newAlert1State.end).not.toBeDefined(); + // @ts-expect-error + expect(newAlert2State.end).not.toBeDefined(); + }); + }); + + describe('activeAlerts', () => { + test('considers alert active if it has scheduled actions', () => { + const newAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const existingAlert1 = new Alert<{}, {}, DefaultActionGroupId>('2'); + const existingAlert2 = new Alert<{}, {}, DefaultActionGroupId>('3'); + + const originalAlerts = { + '2': existingAlert1, + '3': existingAlert2, + }; + + const updatedAlerts = { + ...cloneDeep(originalAlerts), + '1': newAlert, + }; + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + updatedAlerts['2'].scheduleActions('default', { foo: '1' }); + updatedAlerts['3'].scheduleActions('default', { foo: '2' }); + + // @ts-expect-error + const { activeAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(activeAlerts).toEqual({ + '1': updatedAlerts['1'], + '2': updatedAlerts['2'], + '3': updatedAlerts['3'], + }); + }); + + test('updates duration in active alerts if start is available', () => { + const newAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const existingAlert1 = new Alert<{}, {}, DefaultActionGroupId>('2'); + const existingAlert2 = new Alert<{}, {}, DefaultActionGroupId>('3'); + + const originalAlerts = { + '2': existingAlert1, + '3': existingAlert2, + }; + originalAlerts['2'].replaceState({ start: '1969-12-30T00:00:00.000Z', duration: 33000 }); + originalAlerts['3'].replaceState({ start: '1969-12-31T07:34:00.000Z', duration: 23532 }); + + const updatedAlerts = { + ...cloneDeep(originalAlerts), + '1': newAlert, + }; + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + updatedAlerts['2'].scheduleActions('default', { foo: '1' }); + updatedAlerts['3'].scheduleActions('default', { foo: '2' }); + + // @ts-expect-error + const { activeAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(activeAlerts).toEqual({ + '1': updatedAlerts['1'], + '2': updatedAlerts['2'], + '3': updatedAlerts['3'], + }); + + const activeAlert1State = activeAlerts['2'].getState(); + const activeAlert2State = activeAlerts['3'].getState(); + + // @ts-expect-error + expect(activeAlert1State.start).toEqual('1969-12-30T00:00:00.000Z'); + // @ts-expect-error + expect(activeAlert2State.start).toEqual('1969-12-31T07:34:00.000Z'); + + // @ts-expect-error + expect(activeAlert1State.duration).toEqual('172800000000000'); + // @ts-expect-error + expect(activeAlert2State.duration).toEqual('59160000000000'); + + // @ts-expect-error + expect(activeAlert1State.end).not.toBeDefined(); + // @ts-expect-error + expect(activeAlert2State.end).not.toBeDefined(); + }); + + test('does not update duration in active alerts if start is not available', () => { + const newAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const existingAlert1 = new Alert<{}, {}, DefaultActionGroupId>('2'); + const existingAlert2 = new Alert<{}, {}, DefaultActionGroupId>('3'); + + const originalAlerts = { + '2': existingAlert1, + '3': existingAlert2, + }; + + const updatedAlerts = { + ...cloneDeep(originalAlerts), + '1': newAlert, + }; + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + updatedAlerts['2'].scheduleActions('default', { foo: '1' }); + updatedAlerts['3'].scheduleActions('default', { foo: '2' }); + + // @ts-expect-error + const { activeAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(activeAlerts).toEqual({ + '1': updatedAlerts['1'], + '2': updatedAlerts['2'], + '3': updatedAlerts['3'], + }); + + const activeAlert1State = activeAlerts['2'].getState(); + const activeAlert2State = activeAlerts['3'].getState(); + + // @ts-expect-error + expect(activeAlert1State.start).not.toBeDefined(); + // @ts-expect-error + expect(activeAlert2State.start).not.toBeDefined(); + + // @ts-expect-error + expect(activeAlert1State.duration).not.toBeDefined(); + // @ts-expect-error + expect(activeAlert2State.duration).not.toBeDefined(); + + // @ts-expect-error + expect(activeAlert1State.end).not.toBeDefined(); + // @ts-expect-error + expect(activeAlert2State.end).not.toBeDefined(); + }); + + test('preserves other state fields', () => { + const newAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const existingAlert1 = new Alert<{}, {}, DefaultActionGroupId>('2'); + const existingAlert2 = new Alert<{}, {}, DefaultActionGroupId>('3'); + + const originalAlerts = { + '2': existingAlert1, + '3': existingAlert2, + }; + originalAlerts['2'].replaceState({ + stateField1: 'xyz', + start: '1969-12-30T00:00:00.000Z', + duration: 33000, + }); + originalAlerts['3'].replaceState({ + anotherState: true, + start: '1969-12-31T07:34:00.000Z', + duration: 23532, + }); + + const updatedAlerts = { + ...cloneDeep(originalAlerts), + '1': newAlert, + }; + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + updatedAlerts['2'].scheduleActions('default', { foo: '1' }); + updatedAlerts['3'].scheduleActions('default', { foo: '2' }); + + // @ts-expect-error + const { activeAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(activeAlerts).toEqual({ + '1': updatedAlerts['1'], + '2': updatedAlerts['2'], + '3': updatedAlerts['3'], + }); + + const activeAlert1State = activeAlerts['2'].getState(); + const activeAlert2State = activeAlerts['3'].getState(); + + // @ts-expect-error + expect(activeAlert1State.start).toEqual('1969-12-30T00:00:00.000Z'); + // @ts-expect-error + expect(activeAlert2State.start).toEqual('1969-12-31T07:34:00.000Z'); + + // @ts-expect-error + expect(activeAlert1State.stateField1).toEqual('xyz'); + // @ts-expect-error + expect(activeAlert2State.anotherState).toEqual(true); + + // @ts-expect-error + expect(activeAlert1State.duration).toEqual('172800000000000'); + // @ts-expect-error + expect(activeAlert2State.duration).toEqual('59160000000000'); + + // @ts-expect-error + expect(activeAlert1State.end).not.toBeDefined(); + // @ts-expect-error + expect(activeAlert2State.end).not.toBeDefined(); + }); + }); + + describe('recoveredAlerts', () => { + test('considers alert recovered if it has no scheduled actions', () => { + const activeAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const recoveredAlert = new Alert<{}, {}, DefaultActionGroupId>('2'); + + const originalAlerts = { + '1': activeAlert, + '2': recoveredAlert, + }; + + const updatedAlerts = cloneDeep(originalAlerts); + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + updatedAlerts['2'].setContext({ foo: '2' }); + + // @ts-expect-error + const { recoveredAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(recoveredAlerts).toEqual({ '2': updatedAlerts['2'] }); + }); + + test('does not consider alert recovered if it has no actions but was not in original alerts list', () => { + const activeAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const notRecoveredAlert = new Alert<{}, {}, DefaultActionGroupId>('2'); + + const originalAlerts = { + '1': activeAlert, + }; + + const updatedAlerts = { + ...cloneDeep(originalAlerts), + '2': notRecoveredAlert, + }; + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + + // @ts-expect-error + const { recoveredAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(recoveredAlerts).toEqual({}); + }); + + test('updates duration in recovered alerts if start is available and adds end time', () => { + const activeAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const recoveredAlert1 = new Alert<{}, {}, DefaultActionGroupId>('2'); + const recoveredAlert2 = new Alert<{}, {}, DefaultActionGroupId>('3'); + + const originalAlerts = { + '1': activeAlert, + '2': recoveredAlert1, + '3': recoveredAlert2, + }; + originalAlerts['2'].replaceState({ start: '1969-12-30T00:00:00.000Z', duration: 33000 }); + originalAlerts['3'].replaceState({ start: '1969-12-31T07:34:00.000Z', duration: 23532 }); + + const updatedAlerts = cloneDeep(originalAlerts); + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + + // @ts-expect-error + const { recoveredAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(recoveredAlerts).toEqual({ '2': updatedAlerts['2'], '3': updatedAlerts['3'] }); + + const recoveredAlert1State = recoveredAlerts['2'].getState(); + const recoveredAlert2State = recoveredAlerts['3'].getState(); + + // @ts-expect-error + expect(recoveredAlert1State.start).toEqual('1969-12-30T00:00:00.000Z'); + // @ts-expect-error + expect(recoveredAlert2State.start).toEqual('1969-12-31T07:34:00.000Z'); + + // @ts-expect-error + expect(recoveredAlert1State.duration).toEqual('172800000000000'); + // @ts-expect-error + expect(recoveredAlert2State.duration).toEqual('59160000000000'); + + // @ts-expect-error + expect(recoveredAlert1State.end).toEqual('1970-01-01T00:00:00.000Z'); + // @ts-expect-error + expect(recoveredAlert2State.end).toEqual('1970-01-01T00:00:00.000Z'); + }); + + test('does not update duration or set end in recovered alerts if start is not available', () => { + const activeAlert = new Alert<{}, {}, DefaultActionGroupId>('1'); + const recoveredAlert1 = new Alert<{}, {}, DefaultActionGroupId>('2'); + const recoveredAlert2 = new Alert<{}, {}, DefaultActionGroupId>('3'); + + const originalAlerts = { + '1': activeAlert, + '2': recoveredAlert1, + '3': recoveredAlert2, + }; + const updatedAlerts = cloneDeep(originalAlerts); + + updatedAlerts['1'].scheduleActions('default', { foo: '1' }); + + // @ts-expect-error + const { recoveredAlerts } = processAlerts(updatedAlerts, originalAlerts); + + expect(recoveredAlerts).toEqual({ '2': updatedAlerts['2'], '3': updatedAlerts['3'] }); + + const recoveredAlert1State = recoveredAlerts['2'].getState(); + const recoveredAlert2State = recoveredAlerts['3'].getState(); + + // @ts-expect-error + expect(recoveredAlert1State.start).not.toBeDefined(); + // @ts-expect-error + expect(recoveredAlert2State.start).not.toBeDefined(); + + // @ts-expect-error + expect(recoveredAlert1State.duration).not.toBeDefined(); + // @ts-expect-error + expect(recoveredAlert2State.duration).not.toBeDefined(); + + // @ts-expect-error + expect(recoveredAlert1State.end).not.toBeDefined(); + // @ts-expect-error + expect(recoveredAlert2State.end).not.toBeDefined(); + }); + }); +}); diff --git a/x-pack/plugins/alerting/server/lib/process_alerts.ts b/x-pack/plugins/alerting/server/lib/process_alerts.ts new file mode 100644 index 0000000000000..f4af401e5113c --- /dev/null +++ b/x-pack/plugins/alerting/server/lib/process_alerts.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { millisToNanos } from '@kbn/event-log-plugin/server'; +import { Alert } from '../alert'; +import { AlertInstanceState, AlertInstanceContext } from '../types'; + +interface ProcessAlertsResult< + State extends AlertInstanceState, + Context extends AlertInstanceContext, + ActionGroupIds extends string, + RecoveryActionGroupId extends string +> { + newAlerts: Record>; + activeAlerts: Record>; + recoveredAlerts: Record>; +} + +export function processAlerts< + State extends AlertInstanceState, + Context extends AlertInstanceContext, + ActionGroupIds extends string, + RecoveryActionGroupId extends string +>( + alerts: Record>, + originalAlerts: Record> +): ProcessAlertsResult { + const originalAlertIds = new Set(Object.keys(originalAlerts)); + + const currentTime = new Date().toISOString(); + const newAlerts: Record> = {}; + const activeAlerts: Record> = {}; + const recoveredAlerts: Record> = {}; + + for (const id in alerts) { + if (alerts.hasOwnProperty(id)) { + // alerts with scheduled actions are considered "active" + if (alerts[id].hasScheduledActions()) { + activeAlerts[id] = alerts[id]; + + // if this alert did not exist in previous run, it is considered "new" + if (!originalAlertIds.has(id)) { + newAlerts[id] = alerts[id]; + + // Inject start time into alert state for new alerts + const state = newAlerts[id].getState(); + newAlerts[id].replaceState({ ...state, start: currentTime, duration: '0' }); + } else { + // this alert did exist in previous run + // calculate duration to date for active alerts + const state = originalAlerts[id].getState(); + const durationInMs = + new Date(currentTime).valueOf() - new Date(state.start as string).valueOf(); + const duration = state.start ? millisToNanos(durationInMs) : undefined; + activeAlerts[id].replaceState({ + ...state, + ...(state.start ? { start: state.start } : {}), + ...(duration !== undefined ? { duration } : {}), + }); + } + } else if (originalAlertIds.has(id)) { + recoveredAlerts[id] = alerts[id]; + + // Inject end time into alert state of recovered alerts + const state = recoveredAlerts[id].getState(); + const durationInMs = + new Date(currentTime).valueOf() - new Date(state.start as string).valueOf(); + const duration = state.start ? millisToNanos(durationInMs) : undefined; + recoveredAlerts[id].replaceState({ + ...state, + ...(duration ? { duration } : {}), + ...(state.start ? { end: currentTime } : {}), + }); + } + } + } + return { recoveredAlerts, newAlerts, activeAlerts }; +} 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 02ff3d469f585..0a60fa24611aa 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -2696,7 +2696,7 @@ export class RulesClient { ...(s.rRule.until ? { until: new Date(s.rRule.until) } : {}), }, })); - const includeSnoozeSchedule = snoozeSchedule !== undefined; + const includeSnoozeSchedule = snoozeSchedule !== undefined && !excludeFromPublicApi; const rule = { id, notifyWhen, diff --git a/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts index f5c839c5006fd..37059924533b2 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts @@ -376,7 +376,6 @@ describe('create()', () => { "interval": "1m", }, "scheduledTaskId": "task-123", - "snoozeSchedule": Array [], "tags": Array [ "foo", ], @@ -1645,7 +1644,6 @@ describe('create()', () => { "interval": "1m", }, "scheduledTaskId": "task-123", - "snoozeSchedule": Array [], "tags": Array [ "foo", ], @@ -1779,7 +1777,6 @@ describe('create()', () => { "interval": "1m", }, "scheduledTaskId": "task-123", - "snoozeSchedule": Array [], "tags": Array [ "foo", ], @@ -1913,7 +1910,6 @@ describe('create()', () => { "interval": "1m", }, "scheduledTaskId": "task-123", - "snoozeSchedule": Array [], "tags": Array [ "foo", ], @@ -2079,7 +2075,6 @@ describe('create()', () => { "interval": "10s", }, "scheduledTaskId": "task-123", - "snoozeSchedule": Array [], "tags": Array [ "foo", ], diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index c78531cf17d31..30a64d11196c9 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -6,12 +6,12 @@ */ import apm from 'elastic-apm-node'; -import { cloneDeep, mapValues, omit, pickBy, without } from 'lodash'; +import { cloneDeep, omit } from 'lodash'; import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import uuid from 'uuid'; import { KibanaRequest, Logger } from '@kbn/core/server'; import { ConcreteTaskInstance, throwUnrecoverableError } from '@kbn/task-manager-plugin/server'; -import { millisToNanos, nanosToMillis } from '@kbn/event-log-plugin/server'; +import { nanosToMillis } from '@kbn/event-log-plugin/server'; import { TaskRunnerContext } from './task_runner_factory'; import { createExecutionHandler, ExecutionHandler } from './create_execution_handler'; import { Alert, createAlertFactory } from '../alert'; @@ -20,9 +20,9 @@ import { ErrorWithReason, executionStatusFromError, executionStatusFromState, - getRecoveredAlerts, ruleExecutionStatusToRaw, isRuleSnoozed, + processAlerts, } from '../lib'; import { Rule, @@ -62,7 +62,6 @@ import { RuleTaskInstance, RuleTaskRunResult, ScheduleActionsForRecoveredAlertsParams, - TrackAlertDurationsParams, RuleRunResult, RuleTaskStateAndMetrics, } from './types'; @@ -89,9 +88,9 @@ export const getDefaultRuleMonitoring = (): RuleMonitoring => ({ export class TaskRunner< Params extends RuleTypeParams, ExtractedParams extends RuleTypeParams, - State extends RuleTypeState, - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext, + RuleState extends RuleTypeState, + State extends AlertInstanceState, + Context extends AlertInstanceContext, ActionGroupIds extends string, RecoveryActionGroupId extends string > { @@ -102,9 +101,9 @@ export class TaskRunner< private ruleType: NormalizedRuleType< Params, ExtractedParams, + RuleState, State, - InstanceState, - InstanceContext, + Context, ActionGroupIds, RecoveryActionGroupId >; @@ -120,9 +119,9 @@ export class TaskRunner< ruleType: NormalizedRuleType< Params, ExtractedParams, + RuleState, State, - InstanceState, - InstanceContext, + Context, ActionGroupIds, RecoveryActionGroupId >, @@ -158,9 +157,9 @@ export class TaskRunner< return createExecutionHandler< Params, ExtractedParams, + RuleState, State, - InstanceState, - InstanceContext, + Context, ActionGroupIds, RecoveryActionGroupId >({ @@ -227,7 +226,7 @@ export class TaskRunner< private async executeAlert( alertId: string, - alert: Alert, + alert: Alert, executionHandler: ExecutionHandler, ruleRunMetricsStore: RuleRunMetricsStore ) { @@ -275,7 +274,11 @@ export class TaskRunner< } = rule; const { params: { alertId: ruleId }, - state: { alertInstances: alertRawInstances = {}, alertTypeState = {}, previousStartedAt }, + state: { + alertInstances: alertRawInstances = {}, + alertTypeState: ruleTypeState = {}, + previousStartedAt, + }, } = this.taskInstance; const executionHandler = this.getExecutionHandler( @@ -293,16 +296,13 @@ export class TaskRunner< const namespace = this.context.spaceIdToNamespace(spaceId); const ruleType = this.ruleTypeRegistry.get(alertTypeId); - const alerts = mapValues< - Record, - Alert - >( - alertRawInstances, - (rawAlert, alertId) => new Alert(alertId, rawAlert) - ); - + const alerts: Record> = {}; + for (const id in alertRawInstances) { + if (alertRawInstances.hasOwnProperty(id)) { + alerts[id] = new Alert(id, alertRawInstances[id]); + } + } const originalAlerts = cloneDeep(alerts); - const originalAlertIds = new Set(Object.keys(originalAlerts)); const ruleLabel = `${this.ruleType.id}:${ruleId}: '${name}'`; @@ -352,8 +352,8 @@ export class TaskRunner< uiSettingsClient: this.context.uiSettings.asScopedToClient(savedObjectsClient), scopedClusterClient: wrappedScopedClusterClient.client(), alertFactory: createAlertFactory< - InstanceState, - InstanceContext, + State, + Context, WithoutReservedActionGroups >({ alerts, @@ -364,7 +364,7 @@ export class TaskRunner< shouldStopExecution: () => this.cancelled, }, params, - state: alertTypeState as State, + state: ruleTypeState as RuleState, startedAt: this.taskInstance.startedAt!, previousStartedAt: previousStartedAt ? new Date(previousStartedAt) : null, spaceId, @@ -423,33 +423,26 @@ export class TaskRunner< ruleRunMetricsStore.setTotalSearchDurationMs(searchMetrics.totalSearchDurationMs); ruleRunMetricsStore.setEsSearchDurationMs(searchMetrics.esSearchDurationMs); - // Cleanup alerts that are no longer scheduling actions to avoid over populating the alertInstances object - const alertsWithScheduledActions = pickBy( - alerts, - (alert: Alert) => alert.hasScheduledActions() - ); - - const recoveredAlerts = getRecoveredAlerts(alerts, originalAlertIds); + const { newAlerts, activeAlerts, recoveredAlerts } = processAlerts< + State, + Context, + ActionGroupIds, + RecoveryActionGroupId + >(alerts, originalAlerts); logActiveAndRecoveredAlerts({ logger: this.logger, - activeAlerts: alertsWithScheduledActions, + activeAlerts, recoveredAlerts, ruleLabel, canSetRecoveryContext: ruleType.doesSetRecoveryContext ?? false, }); - trackAlertDurations({ - originalAlerts, - currentAlerts: alertsWithScheduledActions, - recoveredAlerts, - }); - if (this.shouldLogAndScheduleActionsForAlerts()) { generateNewAndRecoveredAlertEvents({ alertingEventLogger: this.alertingEventLogger, - originalAlerts, - currentAlerts: alertsWithScheduledActions, + newAlerts, + activeAlerts, recoveredAlerts, ruleLabel, ruleRunMetricsStore, @@ -466,8 +459,8 @@ export class TaskRunner< if (!ruleIsSnoozed && this.shouldLogAndScheduleActionsForAlerts()) { const mutedAlertIdsSet = new Set(mutedInstanceIds); - const alertsWithExecutableActions = Object.entries(alertsWithScheduledActions).filter( - ([alertName, alert]: [string, Alert]) => { + const alertsWithExecutableActions = Object.entries(activeAlerts).filter( + ([alertName, alert]: [string, Alert]) => { const throttled = alert.isThrottled(throttle); const muted = mutedAlertIdsSet.has(alertName); let shouldExecuteAction = true; @@ -495,16 +488,12 @@ export class TaskRunner< await Promise.all( alertsWithExecutableActions.map( - ([alertId, alert]: [string, Alert]) => + ([alertId, alert]: [string, Alert]) => this.executeAlert(alertId, alert, executionHandler, ruleRunMetricsStore) ) ); - await scheduleActionsForRecoveredAlerts< - InstanceState, - InstanceContext, - RecoveryActionGroupId - >({ + await scheduleActionsForRecoveredAlerts({ recoveryActionGroup: this.ruleType.recoveryActionGroup, recoveredAlerts, executionHandler, @@ -530,13 +519,17 @@ export class TaskRunner< } } + const alertsToReturn: Record = {}; + for (const id in activeAlerts) { + if (activeAlerts.hasOwnProperty(id)) { + alertsToReturn[id] = activeAlerts[id].toRaw(); + } + } + return { metrics: ruleRunMetricsStore.getMetrics(), alertTypeState: updatedRuleTypeState || undefined, - alertInstances: mapValues< - Record>, - RawAlertInstance - >(alertsWithScheduledActions, (alert) => alert.toRaw()), + alertInstances: alertsToReturn, }; } @@ -811,76 +804,33 @@ export class TaskRunner< } } -function trackAlertDurations< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext ->(params: TrackAlertDurationsParams) { - const currentTime = new Date().toISOString(); - const { currentAlerts, originalAlerts, recoveredAlerts } = params; - const originalAlertIds = Object.keys(originalAlerts); - const currentAlertIds = Object.keys(currentAlerts); - const recoveredAlertIds = Object.keys(recoveredAlerts); - const newAlertIds = without(currentAlertIds, ...originalAlertIds); - - // Inject start time into alert state of new alerts - for (const id of newAlertIds) { - const state = currentAlerts[id].getState(); - currentAlerts[id].replaceState({ ...state, start: currentTime }); - } - - // Calculate duration to date for active alerts - for (const id of currentAlertIds) { - const state = originalAlertIds.includes(id) - ? originalAlerts[id].getState() - : currentAlerts[id].getState(); - const durationInMs = - new Date(currentTime).valueOf() - new Date(state.start as string).valueOf(); - const duration = state.start ? millisToNanos(durationInMs) : undefined; - currentAlerts[id].replaceState({ - ...state, - ...(state.start ? { start: state.start } : {}), - ...(duration !== undefined ? { duration } : {}), - }); - } - - // Inject end time into alert state of recovered alerts - for (const id of recoveredAlertIds) { - const state = recoveredAlerts[id].getState(); - const durationInMs = - new Date(currentTime).valueOf() - new Date(state.start as string).valueOf(); - const duration = state.start ? millisToNanos(durationInMs) : undefined; - recoveredAlerts[id].replaceState({ - ...state, - ...(duration ? { duration } : {}), - ...(state.start ? { end: currentTime } : {}), - }); - } -} - function generateNewAndRecoveredAlertEvents< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext ->(params: GenerateNewAndRecoveredAlertEventsParams) { - const { - alertingEventLogger, - currentAlerts, - originalAlerts, - recoveredAlerts, - ruleRunMetricsStore, - } = params; - const originalAlertIds = Object.keys(originalAlerts); - const currentAlertIds = Object.keys(currentAlerts); + State extends AlertInstanceState, + Context extends AlertInstanceContext, + ActionGroupIds extends string, + RecoveryActionGroupId extends string +>( + params: GenerateNewAndRecoveredAlertEventsParams< + State, + Context, + ActionGroupIds, + RecoveryActionGroupId + > +) { + const { alertingEventLogger, activeAlerts, newAlerts, recoveredAlerts, ruleRunMetricsStore } = + params; + const activeAlertIds = Object.keys(activeAlerts); const recoveredAlertIds = Object.keys(recoveredAlerts); - const newIds = without(currentAlertIds, ...originalAlertIds); + const newAlertIds = Object.keys(newAlerts); if (apm.currentTransaction) { apm.currentTransaction.addLabels({ - alerting_new_alerts: newIds.length, + alerting_new_alerts: newAlertIds.length, }); } - ruleRunMetricsStore.setNumberOfActiveAlerts(currentAlertIds.length); - ruleRunMetricsStore.setNumberOfNewAlerts(newIds.length); + ruleRunMetricsStore.setNumberOfActiveAlerts(activeAlertIds.length); + ruleRunMetricsStore.setNumberOfNewAlerts(newAlertIds.length); ruleRunMetricsStore.setNumberOfRecoveredAlerts(recoveredAlertIds.length); for (const id of recoveredAlertIds) { @@ -899,10 +849,10 @@ function generateNewAndRecoveredAlertEvents< }); } - for (const id of newIds) { + for (const id of newAlertIds) { const { actionGroup, subgroup: actionSubgroup } = - currentAlerts[id].getScheduledActionOptions() ?? {}; - const state = currentAlerts[id].getState(); + activeAlerts[id].getScheduledActionOptions() ?? {}; + const state = activeAlerts[id].getState(); const message = `${params.ruleLabel} created new alert: '${id}'`; alertingEventLogger.logAlert({ action: EVENT_LOG_ACTIONS.newInstance, @@ -914,10 +864,10 @@ function generateNewAndRecoveredAlertEvents< }); } - for (const id of currentAlertIds) { + for (const id of activeAlertIds) { const { actionGroup, subgroup: actionSubgroup } = - currentAlerts[id].getScheduledActionOptions() ?? {}; - const state = currentAlerts[id].getState(); + activeAlerts[id].getScheduledActionOptions() ?? {}; + const state = activeAlerts[id].getState(); const message = `${params.ruleLabel} active alert: '${id}' in ${ actionSubgroup ? `actionGroup(subgroup): '${actionGroup}(${actionSubgroup})'` @@ -978,17 +928,12 @@ async function scheduleActionsForRecoveredAlerts< } function logActiveAndRecoveredAlerts< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext, + State extends AlertInstanceState, + Context extends AlertInstanceContext, ActionGroupIds extends string, RecoveryActionGroupId extends string >( - params: LogActiveAndRecoveredAlertsParams< - InstanceState, - InstanceContext, - ActionGroupIds, - RecoveryActionGroupId - > + params: LogActiveAndRecoveredAlertsParams ) { const { logger, activeAlerts, recoveredAlerts, ruleLabel, canSetRecoveryContext } = params; const activeAlertIds = Object.keys(activeAlerts); diff --git a/x-pack/plugins/alerting/server/task_runner/types.ts b/x-pack/plugins/alerting/server/task_runner/types.ts index 12de4ccc63a66..7a3a78c5426df 100644 --- a/x-pack/plugins/alerting/server/task_runner/types.ts +++ b/x-pack/plugins/alerting/server/task_runner/types.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { Dictionary } from 'lodash'; import { KibanaRequest, Logger } from '@kbn/core/server'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; import { PluginStartContract as ActionsPluginStartContract } from '@kbn/actions-plugin/server'; @@ -49,23 +48,16 @@ export interface RuleTaskInstance extends ConcreteTaskInstance { state: RuleTaskState; } -export interface TrackAlertDurationsParams< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext -> { - originalAlerts: Dictionary>; - currentAlerts: Dictionary>; - recoveredAlerts: Dictionary>; -} - export interface GenerateNewAndRecoveredAlertEventsParams< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext + State extends AlertInstanceState, + Context extends AlertInstanceContext, + ActionGroupIds extends string, + RecoveryActionGroupId extends string > { alertingEventLogger: AlertingEventLogger; - originalAlerts: Dictionary>; - currentAlerts: Dictionary>; - recoveredAlerts: Dictionary>; + newAlerts: Record>; + activeAlerts: Record>; + recoveredAlerts: Record>; ruleLabel: string; ruleRunMetricsStore: RuleRunMetricsStore; } @@ -77,22 +69,22 @@ export interface ScheduleActionsForRecoveredAlertsParams< > { logger: Logger; recoveryActionGroup: ActionGroup; - recoveredAlerts: Dictionary>; - executionHandler: ExecutionHandler; + recoveredAlerts: Record>; + executionHandler: ExecutionHandler; mutedAlertIdsSet: Set; ruleLabel: string; ruleRunMetricsStore: RuleRunMetricsStore; } export interface LogActiveAndRecoveredAlertsParams< - InstanceState extends AlertInstanceState, - InstanceContext extends AlertInstanceContext, + State extends AlertInstanceState, + Context extends AlertInstanceContext, ActionGroupIds extends string, RecoveryActionGroupId extends string > { logger: Logger; - activeAlerts: Dictionary>; - recoveredAlerts: Dictionary>; + activeAlerts: Record>; + recoveredAlerts: Record>; ruleLabel: string; canSetRecoveryContext: boolean; } diff --git a/x-pack/plugins/apm/scripts/precommit.js b/x-pack/plugins/apm/scripts/precommit.js index ab19094c4e610..c1847432abcf7 100644 --- a/x-pack/plugins/apm/scripts/precommit.js +++ b/x-pack/plugins/apm/scripts/precommit.js @@ -80,7 +80,11 @@ const tasks = new Listr( ), }, ], - { exitOnError: true, concurrent: false } + { + exitOnError: true, + concurrent: false, + renderer: process.env.CI ? 'verbose' : 'default', + } ); tasks.run().catch((error) => { diff --git a/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts b/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts deleted file mode 100644 index 545e90914f4d2..0000000000000 --- a/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { rangeQuery } from '@kbn/observability-plugin/server'; -import { SetupUX } from '../routes/rum_client/route'; -import { - AGENT_NAME, - TRANSACTION_TYPE, - SERVICE_LANGUAGE_NAME, -} from '../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../common/processor_event'; -import { TRANSACTION_PAGE_LOAD } from '../../common/transaction_types'; -import { getEsFilter } from '../routes/rum_client/ui_filters/get_es_filter'; - -export function getRumPageLoadTransactionsProjection({ - setup, - urlQuery, - checkFetchStartFieldExists = true, - start, - end, -}: { - setup: SetupUX; - urlQuery?: string; - checkFetchStartFieldExists?: boolean; - start: number; - end: number; -}) { - const { uiFilters } = setup; - - const bool = { - filter: [ - ...rangeQuery(start, end), - { term: { [TRANSACTION_TYPE]: TRANSACTION_PAGE_LOAD } }, - ...(checkFetchStartFieldExists - ? [ - { - // Adding this filter to cater for some inconsistent rum data - // not available on aggregated transactions - exists: { - field: 'transaction.marks.navigationTiming.fetchStart', - }, - }, - ] - : []), - ...(urlQuery - ? [ - { - wildcard: { - 'url.full': `*${urlQuery}*`, - }, - }, - ] - : []), - ...getEsFilter(uiFilters), - ], - must_not: [...getEsFilter(uiFilters, true)], - }; - - return { - apm: { - events: [ProcessorEvent.transaction], - }, - body: { - query: { - bool, - }, - }, - }; -} - -export function getRumErrorsProjection({ - setup, - urlQuery, - start, - end, -}: { - setup: SetupUX; - urlQuery?: string; - start: number; - end: number; -}) { - const { uiFilters } = setup; - - const bool = { - filter: [ - ...rangeQuery(start, end), - { term: { [AGENT_NAME]: 'rum-js' } }, - { - term: { - [SERVICE_LANGUAGE_NAME]: 'javascript', - }, - }, - ...getEsFilter(uiFilters), - ...(urlQuery - ? [ - { - wildcard: { - 'url.full': `*${urlQuery}*`, - }, - }, - ] - : []), - ], - must_not: [...getEsFilter(uiFilters, true)], - }; - - return { - apm: { - events: [ProcessorEvent.error], - }, - body: { - query: { - bool, - }, - }, - }; -} diff --git a/x-pack/plugins/apm/server/projections/typings.ts b/x-pack/plugins/apm/server/projections/typings.ts deleted file mode 100644 index 6ba7d315bfa6d..0000000000000 --- a/x-pack/plugins/apm/server/projections/typings.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { AggregationOptionsByType } from '@kbn/core/types/elasticsearch'; -import { APMEventESSearchRequest } from '../lib/helpers/create_es_client/create_apm_event_client'; - -export type Projection = Omit & { - body: Omit< - Required['body'], - 'aggs' | 'aggregations' | 'size' - > & { - size?: number; - aggs?: { - [key: string]: { - terms: AggregationOptionsByType['terms'] & { field: string }; - aggs?: Record; - }; - }; - }; -}; diff --git a/x-pack/plugins/apm/server/projections/util/merge_projection/index.test.ts b/x-pack/plugins/apm/server/projections/util/merge_projection/index.test.ts deleted file mode 100644 index 8294630dad9d4..0000000000000 --- a/x-pack/plugins/apm/server/projections/util/merge_projection/index.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { mergeProjection } from '.'; - -describe('mergeProjection', () => { - it('overrides arrays', () => { - expect( - mergeProjection( - { - apm: { events: [] }, - body: { query: { bool: { must: [{ terms: { field: ['a'] } }] } } }, - }, - { - apm: { events: [] }, - body: { query: { bool: { must: [{ term: { field: 'b' } }] } } }, - } - ) - ).toEqual({ - apm: { - events: [], - }, - body: { - query: { - bool: { - must: [ - { - term: { field: 'b' }, - }, - ], - }, - }, - }, - }); - }); - - it('merges plain objects', () => { - const termsAgg = { terms: { field: 'bar' } }; - expect( - mergeProjection( - { apm: { events: [] }, body: { query: {}, aggs: { foo: termsAgg } } }, - { - apm: { - events: [], - }, - body: { - aggs: { - foo: { ...termsAgg, aggs: { bar: { terms: { field: 'baz' } } } }, - }, - }, - } - ) - ).toEqual({ - apm: { - events: [], - }, - body: { - query: {}, - aggs: { - foo: { - terms: { - field: 'bar', - }, - aggs: { - bar: { - terms: { - field: 'baz', - }, - }, - }, - }, - }, - }, - }); - }); -}); diff --git a/x-pack/plugins/apm/server/projections/util/merge_projection/index.ts b/x-pack/plugins/apm/server/projections/util/merge_projection/index.ts deleted file mode 100644 index 992f47c9c1066..0000000000000 --- a/x-pack/plugins/apm/server/projections/util/merge_projection/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { cloneDeep, isPlainObject, mergeWith } from 'lodash'; -import { DeepPartial } from 'utility-types'; -import { APMEventESSearchRequest } from '../../../lib/helpers/create_es_client/create_apm_event_client'; -import { Projection } from '../../typings'; - -type PlainObject = Record; - -type SourceProjection = DeepPartial; - -type DeepMerge = U extends PlainObject - ? T extends PlainObject - ? Omit & { - [key in keyof U]: T extends { [k in key]: any } - ? DeepMerge - : U[key]; - } - : U - : U; - -export function mergeProjection< - T extends Projection, - U extends SourceProjection ->(target: T, source: U): DeepMerge { - return mergeWith({}, cloneDeep(target), source, (a, b) => { - if (isPlainObject(a) && isPlainObject(b)) { - return undefined; - } - return b; - }) as DeepMerge; -} diff --git a/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts b/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts index 4c6bc38192fa4..f906d6d95feb0 100644 --- a/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts +++ b/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts @@ -26,7 +26,6 @@ import { infrastructureRouteRepository } from '../infrastructure/route'; import { latencyDistributionRouteRepository } from '../latency_distribution/route'; import { metricsRouteRepository } from '../metrics/route'; import { observabilityOverviewRouteRepository } from '../observability_overview/route'; -import { rumRouteRepository } from '../rum_client/route'; import { serviceRouteRepository } from '../services/route'; import { serviceGroupRouteRepository } from '../service_groups/route'; import { serviceMapRouteRepository } from '../service_map/route'; @@ -50,7 +49,6 @@ function getTypedGlobalApmServerRouteRepository() { ...latencyDistributionRouteRepository, ...metricsRouteRepository, ...observabilityOverviewRouteRepository, - ...rumRouteRepository, ...serviceMapRouteRepository, ...serviceNodeRouteRepository, ...serviceRouteRepository, diff --git a/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_histogram_range_steps.ts b/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_histogram_range_steps.ts index 6cca44ad6c1ff..349eb1a400f7b 100644 --- a/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_histogram_range_steps.ts +++ b/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_histogram_range_steps.ts @@ -9,10 +9,13 @@ import { scaleLog } from 'd3-scale'; import { isFiniteNumber } from '@kbn/observability-plugin/common/utils/is_finite_number'; import { CommonCorrelationsQueryParams } from '../../../../common/correlations/types'; +import { + SPAN_DURATION, + TRANSACTION_DURATION, +} from '../../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../../common/processor_event'; import { Setup } from '../../../lib/helpers/setup_request'; import { getCommonCorrelationsQuery } from './get_common_correlations_query'; -import { getDurationField } from '../utils'; const getHistogramRangeSteps = (min: number, max: number, steps: number) => { // A d3 based scale function as a helper to get equally distributed bins on a log scale. @@ -39,7 +42,8 @@ export const fetchDurationHistogramRangeSteps = async ({ const steps = 100; - const durationField = getDurationField(eventType); + const durationField = + eventType === ProcessorEvent.span ? SPAN_DURATION : TRANSACTION_DURATION; const resp = await apmEventClient.search( 'get_duration_histogram_range_steps', diff --git a/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_percentiles.ts b/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_percentiles.ts index d9a660ea7e54d..706ccb72dba31 100644 --- a/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_percentiles.ts +++ b/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_percentiles.ts @@ -5,12 +5,15 @@ * 2.0. */ +import { + SPAN_DURATION, + TRANSACTION_DURATION, +} from '../../../../common/elasticsearch_fieldnames'; import { SIGNIFICANT_VALUE_DIGITS } from '../../../../common/correlations/constants'; import { Setup } from '../../../lib/helpers/setup_request'; import { ProcessorEvent } from '../../../../common/processor_event'; import { getCommonCorrelationsQuery } from './get_common_correlations_query'; import { CommonCorrelationsQueryParams } from '../../../../common/correlations/types'; -import { getDurationField } from '../utils'; export const fetchDurationPercentiles = async ({ eventType, @@ -29,34 +32,36 @@ export const fetchDurationPercentiles = async ({ totalDocs: number; percentiles: Record; }> => { - const params = { - apm: { events: [eventType] }, - body: { - track_total_hits: true, - query: getCommonCorrelationsQuery({ - start, - end, - environment, - kuery, - query, - }), - size: 0, - aggs: { - duration_percentiles: { - percentiles: { - hdr: { - number_of_significant_value_digits: SIGNIFICANT_VALUE_DIGITS, + const response = await setup.apmEventClient.search( + 'get_duration_percentiles', + { + apm: { events: [eventType] }, + body: { + track_total_hits: true, + query: getCommonCorrelationsQuery({ + start, + end, + environment, + kuery, + query, + }), + size: 0, + aggs: { + duration_percentiles: { + percentiles: { + hdr: { + number_of_significant_value_digits: SIGNIFICANT_VALUE_DIGITS, + }, + field: + eventType === ProcessorEvent.span + ? SPAN_DURATION + : TRANSACTION_DURATION, + ...(Array.isArray(percents) ? { percents } : {}), }, - field: getDurationField(eventType), - ...(Array.isArray(percents) ? { percents } : {}), }, }, }, - }, - }; - const response = await setup.apmEventClient.search( - 'get_duration_percentiles', - params + } ); // return early with no results if the search didn't return any documents diff --git a/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_ranges.ts b/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_ranges.ts index a7833232ce74b..30dc52b1a6e93 100644 --- a/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_ranges.ts +++ b/x-pack/plugins/apm/server/routes/correlations/queries/fetch_duration_ranges.ts @@ -6,11 +6,14 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { + SPAN_DURATION, + TRANSACTION_DURATION, +} from '../../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../../common/processor_event'; import { Setup } from '../../../lib/helpers/setup_request'; import { getCommonCorrelationsQuery } from './get_common_correlations_query'; import { Environment } from '../../../../common/environment_rt'; -import { getDurationField } from '../utils'; export const fetchDurationRanges = async ({ rangeSteps, @@ -61,7 +64,10 @@ export const fetchDurationRanges = async ({ aggs: { logspace_ranges: { range: { - field: getDurationField(eventType), + field: + eventType === ProcessorEvent.span + ? SPAN_DURATION + : TRANSACTION_DURATION, ranges, }, }, diff --git a/x-pack/plugins/apm/server/routes/correlations/utils/get_duration_field.ts b/x-pack/plugins/apm/server/routes/correlations/utils/get_duration_field.ts deleted file mode 100644 index 4a2ad92d81c7e..0000000000000 --- a/x-pack/plugins/apm/server/routes/correlations/utils/get_duration_field.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - SPAN_DURATION, - TRANSACTION_DURATION, - TRANSACTION_DURATION_HISTOGRAM, -} from '../../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../../common/processor_event'; - -export function getDurationField(eventType: ProcessorEvent) { - switch (eventType) { - case ProcessorEvent.metric: - return TRANSACTION_DURATION_HISTOGRAM; - case ProcessorEvent.span: - return SPAN_DURATION; - default: - return TRANSACTION_DURATION; - } -} diff --git a/x-pack/plugins/apm/server/routes/correlations/utils/index.ts b/x-pack/plugins/apm/server/routes/correlations/utils/index.ts index 25bd53f0c7d0c..f7c5abef939b9 100644 --- a/x-pack/plugins/apm/server/routes/correlations/utils/index.ts +++ b/x-pack/plugins/apm/server/routes/correlations/utils/index.ts @@ -7,4 +7,3 @@ export { computeExpectationsAndRanges } from './compute_expectations_and_ranges'; export { splitAllSettledPromises } from './split_all_settled_promises'; -export { getDurationField } from './get_duration_field'; diff --git a/x-pack/plugins/apm/server/routes/latency_distribution/route.ts b/x-pack/plugins/apm/server/routes/latency_distribution/route.ts index 7ec8d9f179816..9ab93e11b974b 100644 --- a/x-pack/plugins/apm/server/routes/latency_distribution/route.ts +++ b/x-pack/plugins/apm/server/routes/latency_distribution/route.ts @@ -11,7 +11,6 @@ import { termQuery } from '@kbn/observability-plugin/server'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getOverallLatencyDistribution } from './get_overall_latency_distribution'; import { setupRequest } from '../../lib/helpers/setup_request'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { environmentRt, kueryRt, rangeRt } from '../default_api_types'; import { @@ -62,18 +61,9 @@ const latencyOverallTransactionDistributionRoute = createApmServerRoute({ termFilters, } = resources.params.body; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ - ...setup, - kuery, - start, - end, - }); - return getOverallLatencyDistribution({ setup, - eventType: searchAggregatedTransactions - ? ProcessorEvent.metric - : ProcessorEvent.transaction, + eventType: ProcessorEvent.transaction, environment, kuery, start, diff --git a/x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap deleted file mode 100644 index c36088481d07c..0000000000000 --- a/x-pack/plugins/apm/server/routes/rum_client/__snapshots__/queries.test.ts.snap +++ /dev/null @@ -1,272 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`rum client dashboard queries fetches page load distribution 1`] = ` -Object { - "apm": Object { - "events": Array [ - "transaction", - ], - }, - "body": Object { - "aggs": Object { - "durPercentiles": Object { - "percentiles": Object { - "field": "transaction.duration.us", - "hdr": Object { - "number_of_significant_value_digits": 3, - }, - "percents": Array [ - 50, - 75, - 90, - 95, - 99, - ], - }, - }, - "loadDistribution": Object { - "percentile_ranks": Object { - "field": "transaction.duration.us", - "hdr": Object { - "number_of_significant_value_digits": 3, - }, - "keyed": false, - "values": Array [ - 0, - 500000, - 1000000, - 1500000, - 2000000, - 2500000, - 3000000, - 3500000, - 4000000, - 4500000, - 5000000, - 5500000, - 6000000, - 6500000, - 7000000, - 7500000, - 8000000, - 8500000, - 9000000, - 9500000, - 10000000, - 10500000, - 11000000, - 11500000, - 12000000, - 12500000, - 13000000, - 13500000, - 14000000, - 14500000, - 15000000, - 15500000, - 16000000, - 16500000, - 17000000, - 17500000, - 18000000, - 18500000, - 19000000, - 19500000, - 20000000, - 20500000, - 21000000, - 21500000, - 22000000, - 22500000, - 23000000, - 23500000, - 24000000, - 24500000, - 25000000, - 25500000, - 26000000, - 26500000, - 27000000, - 27500000, - 28000000, - 28500000, - 29000000, - 29500000, - 30000000, - 30500000, - 31000000, - 31500000, - 32000000, - 32500000, - 33000000, - 33500000, - 34000000, - 34500000, - 35000000, - 35500000, - 36000000, - 36500000, - 37000000, - 37500000, - 38000000, - 38500000, - 39000000, - 39500000, - 40000000, - 40500000, - 41000000, - 41500000, - 42000000, - 42500000, - 43000000, - 43500000, - 44000000, - 44500000, - 45000000, - 45500000, - 46000000, - 46500000, - 47000000, - 47500000, - 48000000, - 48500000, - 49000000, - 49500000, - 50000000, - 50500000, - 51000000, - 51500000, - 52000000, - 52500000, - 53000000, - 53500000, - 54000000, - 54500000, - 55000000, - 55500000, - 56000000, - 56500000, - 57000000, - 57500000, - 58000000, - 58500000, - 59000000, - 59500000, - 60000000, - 60500000, - 61000000, - 61500000, - 62000000, - 62500000, - 63000000, - 63500000, - 64000000, - 64500000, - 65000000, - 65500000, - 66000000, - 66500000, - 67000000, - 67500000, - 68000000, - 68500000, - 69000000, - 69500000, - 70000000, - 70500000, - 71000000, - 71500000, - 72000000, - 72500000, - 73000000, - 73500000, - 74000000, - 74500000, - 75000000, - 75500000, - 76000000, - 76500000, - 77000000, - 77500000, - 78000000, - 78500000, - 79000000, - 79500000, - 80000000, - 80500000, - 81000000, - 81500000, - 82000000, - 82500000, - 83000000, - 83500000, - 84000000, - 84500000, - 85000000, - 85500000, - 86000000, - 86500000, - 87000000, - 87500000, - 88000000, - 88500000, - 89000000, - 89500000, - 90000000, - 90500000, - 91000000, - 91500000, - 92000000, - 92500000, - 93000000, - 93500000, - 94000000, - 94500000, - 95000000, - 95500000, - 96000000, - 96500000, - 97000000, - 97500000, - 98000000, - 98500000, - 99000000, - ], - }, - }, - }, - "query": Object { - "bool": Object { - "filter": Array [ - Object { - "range": Object { - "@timestamp": Object { - "format": "epoch_millis", - "gte": 0, - "lte": 50000, - }, - }, - }, - Object { - "term": Object { - "transaction.type": "page-load", - }, - }, - Object { - "exists": Object { - "field": "transaction.marks.navigationTiming.fetchStart", - }, - }, - Object { - "term": Object { - "service.environment": "staging", - }, - }, - ], - "must_not": Array [], - }, - }, - "size": 0, - }, -} -`; diff --git a/x-pack/plugins/apm/server/routes/rum_client/get_page_load_distribution.ts b/x-pack/plugins/apm/server/routes/rum_client/get_page_load_distribution.ts deleted file mode 100644 index 27c8c4668ce9b..0000000000000 --- a/x-pack/plugins/apm/server/routes/rum_client/get_page_load_distribution.ts +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { TRANSACTION_DURATION } from '../../../common/elasticsearch_fieldnames'; -import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; -import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from './route'; - -export const MICRO_TO_SEC = 1000000; - -export function microToSec(val: number) { - return Math.round((val / MICRO_TO_SEC + Number.EPSILON) * 100) / 100; -} - -export function removeZeroesFromTail( - distData: Array<{ x: number; y: number }> -) { - if (distData.length > 0) { - while (distData[distData.length - 1].y === 0) { - distData.pop(); - } - } - return distData; -} - -export const getPLDChartSteps = ({ - maxDuration, - minDuration, - initStepValue, -}: { - maxDuration: number; - minDuration: number; - initStepValue?: number; -}) => { - let stepValue = 0.5; - // if diff is too low, let's lower - // down the steps value to increase steps - if (maxDuration - minDuration <= 5 * MICRO_TO_SEC) { - stepValue = 0.1; - } - - if (initStepValue) { - stepValue = initStepValue; - } - - let initValue = minDuration; - const stepValues = [initValue]; - - while (initValue < maxDuration) { - initValue += stepValue * MICRO_TO_SEC; - stepValues.push(initValue); - } - - return stepValues; -}; - -export async function getPageLoadDistribution({ - setup, - minPercentile, - maxPercentile, - urlQuery, - start, - end, -}: { - setup: SetupUX; - minPercentile?: string; - maxPercentile?: string; - urlQuery?: string; - start: number; - end: number; -}) { - const projection = getRumPageLoadTransactionsProjection({ - setup, - urlQuery, - start, - end, - }); - - // we will first get 100 steps using 0sec and 50sec duration, - // most web apps will cover this use case - // if 99th percentile is greater than 50sec, - // we will fetch additional 5 steps beyond 99th percentile - let maxDuration = (maxPercentile ? +maxPercentile : 50) * MICRO_TO_SEC; - const minDuration = minPercentile ? +minPercentile * MICRO_TO_SEC : 0; - const stepValues = getPLDChartSteps({ - maxDuration, - minDuration, - }); - - const params = mergeProjection(projection, { - body: { - size: 0, - aggs: { - durPercentiles: { - percentiles: { - field: TRANSACTION_DURATION, - percents: [50, 75, 90, 95, 99], - hdr: { - number_of_significant_value_digits: 3, - }, - }, - }, - loadDistribution: { - percentile_ranks: { - field: TRANSACTION_DURATION, - values: stepValues, - keyed: false, - hdr: { - number_of_significant_value_digits: 3, - }, - }, - }, - }, - }, - }); - - const { apmEventClient } = setup; - - const { - aggregations, - hits: { total }, - } = await apmEventClient.search('get_page_load_distribution', params); - - if (total.value === 0) { - return null; - } - - const { durPercentiles, loadDistribution } = aggregations ?? {}; - - let pageDistVals = loadDistribution?.values ?? []; - - const maxPercQuery = durPercentiles?.values['99.0'] ?? 0; - - // we assumed that page load will never exceed 50secs, if 99th percentile is - // greater then let's fetch additional 10 steps, to cover that on the chart - if (maxPercQuery > maxDuration && !maxPercentile) { - const additionalStepsPageVals = await getPercentilesDistribution({ - setup, - maxDuration: maxPercQuery, - // we pass 50sec as min to get next steps - minDuration: maxDuration, - start, - end, - }); - - pageDistVals = pageDistVals.concat(additionalStepsPageVals); - maxDuration = maxPercQuery; - } - - // calculate the diff to get actual page load on specific duration value - let pageDist = pageDistVals.map( - ({ key, value: maybeNullValue }, index: number, arr) => { - // FIXME: values from percentile* aggs can be null - const value = maybeNullValue!; - return { - x: microToSec(key), - y: index === 0 ? value : value - arr[index - 1].value!, - }; - } - ); - - pageDist = removeZeroesFromTail(pageDist); - - Object.entries(durPercentiles?.values ?? {}).forEach(([key, val]) => { - if (durPercentiles?.values?.[key]) { - durPercentiles.values[key] = microToSec(val as number); - } - }); - - return { - pageLoadDistribution: pageDist, - percentiles: durPercentiles?.values, - minDuration: microToSec(minDuration), - maxDuration: microToSec(maxDuration), - }; -} - -const getPercentilesDistribution = async ({ - setup, - minDuration, - maxDuration, - start, - end, -}: { - setup: SetupUX; - minDuration: number; - maxDuration: number; - start: number; - end: number; -}) => { - const stepValues = getPLDChartSteps({ - minDuration: minDuration + 0.5 * MICRO_TO_SEC, - maxDuration, - initStepValue: 0.5, - }); - - const projection = getRumPageLoadTransactionsProjection({ - setup, - start, - end, - }); - - const params = mergeProjection(projection, { - body: { - size: 0, - aggs: { - loadDistribution: { - percentile_ranks: { - field: TRANSACTION_DURATION, - values: stepValues, - keyed: false, - hdr: { - number_of_significant_value_digits: 3, - }, - }, - }, - }, - }, - }); - - const { apmEventClient } = setup; - - const { aggregations } = await apmEventClient.search( - 'get_page_load_distribution', - params - ); - - return aggregations?.loadDistribution.values ?? []; -}; diff --git a/x-pack/plugins/apm/server/routes/rum_client/get_pl_dist_breakdown.ts b/x-pack/plugins/apm/server/routes/rum_client/get_pl_dist_breakdown.ts deleted file mode 100644 index d6a67b57fa98f..0000000000000 --- a/x-pack/plugins/apm/server/routes/rum_client/get_pl_dist_breakdown.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getRumPageLoadTransactionsProjection } from '../../projections/rum_page_load_transactions'; -import { ProcessorEvent } from '../../../common/processor_event'; -import { mergeProjection } from '../../projections/util/merge_projection'; -import { SetupUX } from './route'; -import { - CLIENT_GEO_COUNTRY_ISO_CODE, - USER_AGENT_DEVICE, - USER_AGENT_NAME, - USER_AGENT_OS, - TRANSACTION_DURATION, -} from '../../../common/elasticsearch_fieldnames'; -import { - getPLDChartSteps, - MICRO_TO_SEC, - microToSec, - removeZeroesFromTail, -} from './get_page_load_distribution'; - -export const getBreakdownField = (breakdown: string) => { - switch (breakdown) { - case 'Location': - return CLIENT_GEO_COUNTRY_ISO_CODE; - case 'Device': - return USER_AGENT_DEVICE; - case 'OS': - return USER_AGENT_OS; - case 'Browser': - default: - return USER_AGENT_NAME; - } -}; - -export const getPageLoadDistBreakdown = async ({ - setup, - minPercentile, - maxPercentile, - breakdown, - urlQuery, - start, - end, -}: { - setup: SetupUX; - minPercentile: number; - maxPercentile: number; - breakdown: string; - urlQuery?: string; - start: number; - end: number; -}) => { - // convert secs to micros - const stepValues = getPLDChartSteps({ - maxDuration: (maxPercentile ? +maxPercentile : 50) * MICRO_TO_SEC, - minDuration: minPercentile ? +minPercentile * MICRO_TO_SEC : 0, - }); - - const projection = getRumPageLoadTransactionsProjection({ - setup, - urlQuery, - start, - end, - }); - - const params = mergeProjection(projection, { - apm: { - events: [ProcessorEvent.transaction], - }, - body: { - size: 0, - aggs: { - breakdowns: { - terms: { - field: getBreakdownField(breakdown), - size: 9, - }, - aggs: { - page_dist: { - percentile_ranks: { - field: TRANSACTION_DURATION, - values: stepValues, - keyed: false, - hdr: { - number_of_significant_value_digits: 3, - }, - }, - }, - }, - }, - }, - }, - }); - - const { apmEventClient } = setup; - - const { aggregations } = await apmEventClient.search( - 'get_page_load_dist_breakdown', - params - ); - - const pageDistBreakdowns = aggregations?.breakdowns.buckets; - - return pageDistBreakdowns?.map(({ key, page_dist: pageDist }) => { - let seriesData = pageDist.values?.map( - ({ key: pKey, value: maybeNullValue }, index: number, arr) => { - // FIXME: values from percentile* aggs can be null - const value = maybeNullValue!; - return { - x: microToSec(pKey), - y: index === 0 ? value : value - arr[index - 1].value!, - }; - } - ); - - // remove 0 values from tail - seriesData = removeZeroesFromTail(seriesData); - - return { - name: String(key), - data: seriesData, - }; - }); -}; diff --git a/x-pack/plugins/apm/server/routes/rum_client/queries.test.ts b/x-pack/plugins/apm/server/routes/rum_client/queries.test.ts deleted file mode 100644 index bbc67fef9d8e1..0000000000000 --- a/x-pack/plugins/apm/server/routes/rum_client/queries.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - SearchParamsMock, - inspectSearchParams, -} from '../../utils/test_helpers'; -import { getPageLoadDistribution } from './get_page_load_distribution'; - -describe('rum client dashboard queries', () => { - let mock: SearchParamsMock; - - afterEach(() => { - mock.teardown(); - }); - - it('fetches page load distribution', async () => { - mock = await inspectSearchParams( - (setup) => - getPageLoadDistribution({ - setup, - minPercentile: '0', - maxPercentile: '99', - start: 0, - end: 50000, - }), - { uiFilters: { environment: 'staging' } } - ); - expect(mock.params).toMatchSnapshot(); - }); -}); diff --git a/x-pack/plugins/apm/server/routes/rum_client/route.ts b/x-pack/plugins/apm/server/routes/rum_client/route.ts deleted file mode 100644 index 834b71223f969..0000000000000 --- a/x-pack/plugins/apm/server/routes/rum_client/route.ts +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import * as t from 'io-ts'; -import { Logger } from '@kbn/core/server'; -import { setupRequest, Setup } from '../../lib/helpers/setup_request'; -import { getPageLoadDistribution } from './get_page_load_distribution'; -import { getPageLoadDistBreakdown } from './get_pl_dist_breakdown'; -import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; -import { rangeRt } from '../default_api_types'; -import { APMRouteHandlerResources } from '../typings'; -import { UxUIFilters } from '../../../common/ux_ui_filter'; - -export type SetupUX = Setup & { - uiFilters: UxUIFilters; -}; - -interface SetupRequestParams { - query: { - _inspect?: boolean; - - /** - * Timestamp in ms since epoch - */ - start?: number; - - /** - * Timestamp in ms since epoch - */ - end?: number; - }; -} - -type SetupUXRequestParams = Omit & { - query: SetupRequestParams['query'] & { - uiFilters?: string; - }; -}; - -export const percentileRangeRt = t.partial({ - minPercentile: t.string, - maxPercentile: t.string, -}); - -const uiFiltersRt = t.type({ uiFilters: t.string }); - -const uxQueryRt = t.intersection([ - uiFiltersRt, - rangeRt, - t.partial({ urlQuery: t.string, percentile: t.string }), -]); - -const rumPageLoadDistributionRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/ux/page-load-distribution', - params: t.type({ - query: t.intersection([uxQueryRt, percentileRangeRt]), - }), - options: { tags: ['access:apm'] }, - handler: async ( - resources - ): Promise<{ - pageLoadDistribution: { - pageLoadDistribution: Array<{ x: number; y: number }>; - percentiles: Record | undefined; - minDuration: number; - maxDuration: number; - } | null; - }> => { - const setup = await setupUXRequest(resources); - - const { - query: { minPercentile, maxPercentile, urlQuery, start, end }, - } = resources.params; - - const pageLoadDistribution = await getPageLoadDistribution({ - setup, - minPercentile, - maxPercentile, - urlQuery, - start, - end, - }); - - return { pageLoadDistribution }; - }, -}); - -const rumPageLoadDistBreakdownRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/ux/page-load-distribution/breakdown', - params: t.type({ - query: t.intersection([ - uxQueryRt, - percentileRangeRt, - t.type({ breakdown: t.string }), - ]), - }), - options: { tags: ['access:apm'] }, - handler: async ( - resources - ): Promise<{ - pageLoadDistBreakdown: - | Array<{ name: string; data: Array<{ x: number; y: number }> }> - | undefined; - }> => { - const setup = await setupUXRequest(resources); - - const { - query: { minPercentile, maxPercentile, breakdown, urlQuery, start, end }, - } = resources.params; - - const pageLoadDistBreakdown = await getPageLoadDistBreakdown({ - setup, - minPercentile: Number(minPercentile), - maxPercentile: Number(maxPercentile), - breakdown, - urlQuery, - start, - end, - }); - - return { pageLoadDistBreakdown }; - }, -}); - -function decodeUiFilters( - logger: Logger, - uiFiltersEncoded?: string -): UxUIFilters { - if (!uiFiltersEncoded) { - return {}; - } - try { - return JSON.parse(uiFiltersEncoded); - } catch (error) { - logger.error(error); - return {}; - } -} - -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -async function setupUXRequest( - resources: APMRouteHandlerResources & { params: TParams } -) { - const setup = await setupRequest(resources); - return { - ...setup, - uiFilters: decodeUiFilters( - resources.logger, - resources.params.query.uiFilters - ), - }; -} - -export const rumRouteRepository = { - ...rumPageLoadDistributionRoute, - ...rumPageLoadDistBreakdownRoute, -}; diff --git a/x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.test.ts b/x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.test.ts deleted file mode 100644 index ba5e318a1901b..0000000000000 --- a/x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.test.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getEsFilter } from './get_es_filter'; - -describe('getEfFilters', function () { - it('should return environment in include filters', function () { - const result = getEsFilter({ - browser: ['Chrome'], - environment: 'production', - }); - - expect(result).toEqual([ - { terms: { 'user_agent.name': ['Chrome'] } }, - { term: { 'service.environment': 'production' } }, - ]); - }); - - it('should not return environment in exclude filters', function () { - const result = getEsFilter( - { browserExcluded: ['Chrome'], environment: 'production' }, - true - ); - - expect(result).toEqual([{ terms: { 'user_agent.name': ['Chrome'] } }]); - }); -}); diff --git a/x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.ts b/x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.ts deleted file mode 100644 index 8d759140fc659..0000000000000 --- a/x-pack/plugins/apm/server/routes/rum_client/ui_filters/get_es_filter.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ESFilter } from '@kbn/core/types/elasticsearch'; -import { environmentQuery } from '../../../../common/utils/environment_query'; -import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; -import { - uxLocalUIFilterNames, - uxLocalUIFilters, - UxUIFilters, -} from '../../../../common/ux_ui_filter'; - -export function getEsFilter(uiFilters: UxUIFilters, exclude?: boolean) { - const localFilterValues = uiFilters; - const mappedFilters = uxLocalUIFilterNames - .filter((name) => { - const validFilter = name in localFilterValues; - if (exclude) { - return name.includes('Excluded') && validFilter; - } - return !name.includes('Excluded') && validFilter; - }) - .map((filterName) => { - const field = uxLocalUIFilters[filterName]; - const value = localFilterValues[filterName]; - - return { - terms: { - [field.fieldName]: value, - }, - }; - }) as ESFilter[]; - - return [ - ...mappedFilters, - ...(exclude - ? [] - : environmentQuery(uiFilters.environment || ENVIRONMENT_ALL.value)), - ]; -} diff --git a/x-pack/plugins/canvas/public/components/es_field_select/index.tsx b/x-pack/plugins/canvas/public/components/es_field_select/index.tsx index 3b3d5aa13fd24..8c0baea681731 100644 --- a/x-pack/plugins/canvas/public/components/es_field_select/index.tsx +++ b/x-pack/plugins/canvas/public/components/es_field_select/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { getFields } from '../../lib/es_service'; import { ESFieldSelect as Component, ESFieldSelectProps as Props } from './es_field_select'; @@ -14,13 +14,19 @@ type ESFieldSelectProps = Omit; export const ESFieldSelect: React.FunctionComponent = (props) => { const { index, value, onChange } = props; const [fields, setFields] = useState([]); + const loadingFields = useRef(false); useEffect(() => { - getFields(index).then((newFields) => setFields(newFields || [])); + loadingFields.current = true; + getFields(index) + .then((newFields) => setFields(newFields || [])) + .finally(() => { + loadingFields.current = false; + }); }, [index]); useEffect(() => { - if (value && !fields.includes(value)) { + if (!loadingFields.current && value && !fields.includes(value)) { onChange(null); } }, [value, fields, onChange]); diff --git a/x-pack/plugins/canvas/public/components/paginate/index.tsx b/x-pack/plugins/canvas/public/components/paginate/index.tsx index 5998b68ffd8bd..bf7c6e09cc01a 100644 --- a/x-pack/plugins/canvas/public/components/paginate/index.tsx +++ b/x-pack/plugins/canvas/public/components/paginate/index.tsx @@ -27,7 +27,8 @@ export const Paginate: React.FunctionComponent = ({ const initialCurrentPage = totalPages > 0 ? Math.min(startPage, totalPages - 1) : 0; const [currentPage, setPage] = useState(initialCurrentPage); const hasRenderedRef = useRef(false); - const maxPage = Math.min(totalPages - 1, 0); + const maxPage = Math.max(totalPages - 1, 0); + const start = currentPage * perPage; const end = currentPage === 0 ? perPage : perPage * (currentPage + 1); const nextPageEnabled = currentPage < maxPage; diff --git a/x-pack/plugins/cases/common/registry.test.ts b/x-pack/plugins/cases/common/registry.test.ts index 2fdda34d3ce91..cce3997630d99 100644 --- a/x-pack/plugins/cases/common/registry.test.ts +++ b/x-pack/plugins/cases/common/registry.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CaseRegistry } from './registry'; +import { AttachmentTypeRegistry } from './registry'; export const ExpressionComponent: React.FunctionComponent = () => { return null; @@ -15,18 +15,18 @@ const getItem = (id: string = 'test') => { return { id }; }; -describe('CaseRegistry', () => { +describe('AttachmentTypeRegistry', () => { beforeEach(() => jest.resetAllMocks()); describe('has()', () => { it('returns false for unregistered items', () => { - const registry = new CaseRegistry('TestRegistry'); + const registry = new AttachmentTypeRegistry('TestRegistry'); expect(registry.has('test')).toEqual(false); }); it('returns true after registering an item', () => { - const registry = new CaseRegistry('TestRegistry'); + const registry = new AttachmentTypeRegistry('TestRegistry'); registry.register(getItem()); expect(registry.has('test')); @@ -35,14 +35,14 @@ describe('CaseRegistry', () => { describe('register()', () => { it('able to register items', () => { - const registry = new CaseRegistry('TestRegistry'); + const registry = new AttachmentTypeRegistry('TestRegistry'); registry.register(getItem()); expect(registry.has('test')).toEqual(true); }); it('throws error if item is already registered', () => { - const registry = new CaseRegistry('TestRegistry'); + const registry = new AttachmentTypeRegistry('TestRegistry'); registry.register(getItem('test')); expect(() => registry.register(getItem('test'))).toThrowErrorMatchingInlineSnapshot( @@ -53,7 +53,7 @@ describe('CaseRegistry', () => { describe('get()', () => { it('returns item', () => { - const registry = new CaseRegistry('TestRegistry'); + const registry = new AttachmentTypeRegistry('TestRegistry'); registry.register(getItem()); const actionType = registry.get('test'); @@ -63,7 +63,7 @@ describe('CaseRegistry', () => { }); it(`throw error when action type doesn't exist`, () => { - const registry = new CaseRegistry('TestRegistry'); + const registry = new AttachmentTypeRegistry('TestRegistry'); expect(() => registry.get('not-exist-item')).toThrowErrorMatchingInlineSnapshot( `"Item \\"not-exist-item\\" is not registered on registry TestRegistry"` ); @@ -72,7 +72,7 @@ describe('CaseRegistry', () => { describe('list()', () => { it('returns list of items', () => { - const actionTypeRegistry = new CaseRegistry('TestRegistry'); + const actionTypeRegistry = new AttachmentTypeRegistry('TestRegistry'); actionTypeRegistry.register(getItem()); const actionTypes = actionTypeRegistry.list(); diff --git a/x-pack/plugins/cases/common/registry.ts b/x-pack/plugins/cases/common/registry.ts index b6ba2c2a004ff..1b3d9969c75b0 100644 --- a/x-pack/plugins/cases/common/registry.ts +++ b/x-pack/plugins/cases/common/registry.ts @@ -7,11 +7,11 @@ import { i18n } from '@kbn/i18n'; -interface BaseItem { +export interface AttachmentTypeRegistryBaseItem { id: string; } -export class CaseRegistry { +export class AttachmentTypeRegistry { private readonly collection: Map = new Map(); constructor(private readonly name: string) {} diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index 7ab5fccafa7bb..65dc8b124c2b1 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -22,6 +22,7 @@ import { CasesMetricsResponse, CaseSeverity, CommentResponseExternalReferenceType, + CommentResponseTypePersistableState, } from '../api'; import { SnakeToCamelCase } from '../types'; @@ -67,6 +68,7 @@ export type CaseViewRefreshPropInterface = null | { export type Comment = SnakeToCamelCase; export type AlertComment = SnakeToCamelCase; export type ExternalReferenceComment = SnakeToCamelCase; +export type PersistableComment = SnakeToCamelCase; export type CaseUserActions = SnakeToCamelCase; export type CaseExternalService = SnakeToCamelCase; export type Case = Omit, 'comments'> & { comments: Comment[] }; diff --git a/x-pack/plugins/cases/common/utils/attachments.ts b/x-pack/plugins/cases/common/utils/attachments.ts new file mode 100644 index 0000000000000..75446ebedb0ed --- /dev/null +++ b/x-pack/plugins/cases/common/utils/attachments.ts @@ -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 { + CommentRequest, + CommentRequestExternalReferenceType, + CommentType, + CommentRequestPersistableStateType, +} from '../api'; + +/** + * A type narrowing function for external reference attachments. + */ +export const isCommentRequestTypeExternalReference = ( + context: CommentRequest +): context is CommentRequestExternalReferenceType => { + return context.type === CommentType.externalReference; +}; + +/** + * A type narrowing function for persistable state attachments. + */ +export const isCommentRequestTypePersistableState = ( + context: Partial +): context is CommentRequestPersistableStateType => { + return context.type === CommentType.persistableState; +}; diff --git a/x-pack/plugins/cases/docs/openapi/bundled.json b/x-pack/plugins/cases/docs/openapi/bundled.json index 13645b108fc0b..9482e4489d875 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.json +++ b/x-pack/plugins/cases/docs/openapi/bundled.json @@ -31,7 +31,8 @@ "paths": { "/api/cases": { "post": { - "summary": "Creates a case.", + "summary": "Creates a case in the default space.", + "operationId": "createCaseDefaultSpace", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're creating.\n", "tags": [ "cases", @@ -484,7 +485,8 @@ ] }, "delete": { - "summary": "Deletes one or more cases.", + "summary": "Deletes one or more cases from the default space.", + "operationId": "deleteCaseDefaultSpace", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're deleting.\n", "tags": [ "cases", @@ -517,7 +519,8 @@ ] }, "patch": { - "summary": "Updates one or more cases.", + "summary": "Updates one or more cases in the default space.", + "operationId": "updateCaseDefaultSpace", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're updating.\n", "tags": [ "cases", @@ -989,7 +992,8 @@ }, "/api/cases/_find": { "get": { - "summary": "Retrieves a paginated subset of cases.", + "summary": "Retrieves a paginated subset of cases from the default space.", + "operationId": "getCasesDefaultSpace", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", "tags": [ "cases", @@ -1494,7 +1498,8 @@ }, "/api/cases/alerts/{alertId}": { "get": { - "summary": "Returns the cases associated with a specific alert.", + "summary": "Returns the cases associated with a specific alert in the default space.", + "operationId": "getCasesByAlertDefaultSpace", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", "x-technical-preview": true, "tags": [ @@ -1554,7 +1559,8 @@ }, "/api/cases/configure": { "get": { - "summary": "Retrieves external connection details, such as the closure type and default connector for cases.", + "summary": "Retrieves external connection details, such as the closure type and default connector for cases in the default space.", + "operationId": "getCaseConfigurationDefaultSpace", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case configuration.\n", "tags": [ "cases", @@ -1762,7 +1768,8 @@ ] }, "post": { - "summary": "Sets external connection details, such as the closure type and default connector for cases.", + "summary": "Sets external connection details, such as the closure type and default connector for cases in the default space.", + "operationId": "setCaseConfigurationDefaultSpace", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case configuration. Connectors are used to interface with external systems. You must create a connector before you can use it in your cases. Refer to the add connectors API. If you set a default connector, it is automatically selected when you create cases in Kibana. If you use the create case API, however, you must still specify all of the connector details.\n", "tags": [ "cases", @@ -2109,7 +2116,8 @@ }, "/api/cases/configure/{configurationId}": { "patch": { - "summary": "Updates external connection details, such as the closure type and default connector for cases.", + "summary": "Updates external connection details, such as the closure type and default connector for cases in the default space.", + "operationId": "updateCaseConfigurationDefaultSpace", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case configuration. Connectors are used to interface with external systems. You must create a connector before you can use it in your cases. Refer to the add connectors API.\n", "tags": [ "cases", @@ -2445,7 +2453,8 @@ }, "/api/cases/configure/connectors/_find": { "get": { - "summary": "Retrieves information about connectors.", + "summary": "Retrieves information about connectors for cases in the default space.", + "operationId": "getCaseConnectorsDefaultSpace", "description": "In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "cases", @@ -2520,7 +2529,8 @@ }, "/api/cases/reporters": { "get": { - "summary": "Returns information about the users who opened cases.", + "summary": "Returns information about the users who opened cases in the default space.", + "operationId": "getCaseReportersDefaultCase", "description": "You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases. The API returns information about the users as they existed at the time of the case creation, including their name, full name, and email address. If any of those details change thereafter or if a user is deleted, the information returned by this API is unchanged.\n", "tags": [ "cases", @@ -2630,7 +2640,8 @@ }, "/api/cases/tags": { "get": { - "summary": "Aggregates and returns a list of case tags.", + "summary": "Aggregates and returns a list of case tags in the default space.", + "operationId": "getCaseTagsDefaultSpace", "description": "You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", "tags": [ "cases", @@ -2688,43 +2699,30 @@ } ] }, - "/api/cases/{caseId}/comments": { - "post": { - "summary": "Adds a comment or alert to a case.", - "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're creating.\n", + "/api/cases/{caseId}": { + "get": { + "summary": "Retrieves information about a case in the default space.", + "operationId": "getCaseDefaultSpace", + "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking.\n", "tags": [ "cases", "kibana" ], "parameters": [ { - "$ref": "#/components/parameters/kbn_xsrf" + "$ref": "#/components/parameters/case_id" }, { - "$ref": "#/components/parameters/case_id" - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/add_alert_comment_request_properties" - }, - { - "$ref": "#/components/schemas/add_user_comment_request_properties" - } - ] - }, - "examples": { - "createCaseCommentRequest": { - "$ref": "#/components/examples/add_comment_request" - } - } + "in": "query", + "name": "includeComments", + "description": "Determines whether case comments are returned.", + "deprecated": true, + "schema": { + "type": "boolean", + "default": true } } - }, + ], "responses": { "200": { "description": "Indicates a successful call.", @@ -3001,8 +2999,8 @@ } }, "examples": { - "createCaseCommentResponse": { - "$ref": "#/components/examples/add_comment_response" + "getCaseResponse": { + "$ref": "#/components/examples/get_case_response" } } } @@ -3015,35 +3013,17 @@ } ] }, - "delete": { - "summary": "Deletes all comments and alerts from a case.", - "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're deleting.\n", - "tags": [ - "cases", - "kibana" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "$ref": "#/components/parameters/case_id" - } - ], - "responses": { - "204": { - "description": "Indicates a successful call." - } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "patch": { - "summary": "Updates a comment or alert in a case.", - "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're updating. NOTE: You cannot change the comment type or the owner of a comment.\n", + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/cases/{caseId}/comments": { + "post": { + "summary": "Adds a comment or alert to a case in the default space.", + "operationId": "addCaseCommentDefaultSpace", + "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're creating.\n", "tags": [ "cases", "kibana" @@ -3062,16 +3042,16 @@ "schema": { "oneOf": [ { - "$ref": "#/components/schemas/update_alert_comment_request_properties" + "$ref": "#/components/schemas/add_alert_comment_request_properties" }, { - "$ref": "#/components/schemas/update_user_comment_request_properties" + "$ref": "#/components/schemas/add_user_comment_request_properties" } ] }, "examples": { - "updateCaseCommentRequest": { - "$ref": "#/components/examples/update_comment_request" + "createCaseCommentRequest": { + "$ref": "#/components/examples/add_comment_request" } } } @@ -3353,8 +3333,8 @@ } }, "examples": { - "updateCaseCommentResponse": { - "$ref": "#/components/examples/update_comment_response" + "createCaseCommentResponse": { + "$ref": "#/components/examples/add_comment_response" } } } @@ -3367,57 +3347,9 @@ } ] }, - "get": { - "summary": "Retrieves all the comments from a case.", - "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.\n", - "tags": [ - "cases", - "kibana" - ], - "deprecated": true, - "parameters": [ - { - "$ref": "#/components/parameters/case_id" - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json; charset=utf-8": { - "schema": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/components/schemas/alert_comment_response_properties" - }, - { - "$ref": "#/components/schemas/user_comment_response_properties" - } - ] - } - } - }, - "examples": {} - } - } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "/api/cases/{caseId}/comments/{commentId}": { "delete": { - "summary": "Deletes a comment or alert from a case.", + "summary": "Deletes all comments and alerts from a case in the default space.", + "operationId": "deleteCaseCommentsDefaultSpace", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're deleting.\n", "tags": [ "cases", @@ -3429,9 +3361,6 @@ }, { "$ref": "#/components/parameters/case_id" - }, - { - "$ref": "#/components/parameters/comment_id" } ], "responses": { @@ -3445,237 +3374,56 @@ } ] }, - "get": { - "summary": "Retrieves a comment from a case.", - "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.\n", + "patch": { + "summary": "Updates a comment or alert in a case in the default space.", + "operationId": "updateCaseCommentDefaultSpace", + "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're updating. NOTE: You cannot change the comment type or the owner of a comment.\n", "tags": [ "cases", "kibana" ], "parameters": [ { - "$ref": "#/components/parameters/case_id" + "$ref": "#/components/parameters/kbn_xsrf" }, { - "$ref": "#/components/parameters/comment_id" + "$ref": "#/components/parameters/case_id" } ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/update_alert_comment_request_properties" + }, + { + "$ref": "#/components/schemas/update_user_comment_request_properties" + } + ] + }, + "examples": { + "updateCaseCommentRequest": { + "$ref": "#/components/examples/update_comment_request" + } + } + } + } + }, "responses": { "200": { "description": "Indicates a successful call.", "content": { "application/json; charset=utf-8": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/alert_comment_response_properties" - }, - { - "$ref": "#/components/schemas/user_comment_response_properties" - } - ] - }, - "examples": { - "getCaseCommentResponse": { - "$ref": "#/components/examples/get_comment_response" - } - } - } - } - } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "/s/{spaceId}/api/cases": { - "post": { - "summary": "Creates a case.", - "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're creating.\n", - "tags": [ - "cases", - "kibana" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "$ref": "#/components/parameters/space_id" - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "connector": { - "description": "An object that contains the connector configuration.", - "type": "object", - "properties": { - "fields": { - "description": "An object containing the connector fields. To create a case without a connector, specify null. If you want to omit any individual field, specify null as its value.", - "nullable": true, - "type": "object", - "properties": { - "caseId": { - "description": "The case identifier for Swimlane connectors.", - "type": "string" - }, - "category": { - "description": "The category of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.", - "type": "string" - }, - "destIp": { - "description": "A comma-separated list of destination IPs for ServiceNow SecOps connectors.", - "type": "string" - }, - "impact": { - "description": "The effect an incident had on business for ServiceNow ITSM connectors.", - "type": "string" - }, - "issueType": { - "description": "The type of issue for Jira connectors.", - "type": "string" - }, - "issueTypes": { - "description": "The type of incident for IBM Resilient connectors.", - "type": "array", - "items": { - "type": "number" - } - }, - "malwareHash": { - "description": "A comma-separated list of malware hashes for ServiceNow SecOps connectors.", - "type": "string" - }, - "malwareUrl": { - "description": "A comma-separated list of malware URLs for ServiceNow SecOps connectors.", - "type": "string" - }, - "parent": { - "description": "The key of the parent issue, when the issue type is sub-task for Jira connectors.", - "type": "string" - }, - "priority": { - "description": "The priority of the issue for Jira and ServiceNow SecOps connectors.", - "type": "string" - }, - "severity": { - "description": "The severity of the incident for ServiceNow ITSM connectors.", - "type": "string" - }, - "severityCode": { - "description": "The severity code of the incident for IBM Resilient connectors.", - "type": "number" - }, - "sourceIp": { - "description": "A comma-separated list of source IPs for ServiceNow SecOps connectors.", - "type": "string" - }, - "subcategory": { - "description": "The subcategory of the incident for ServiceNow ITSM connectors.", - "type": "string" - }, - "urgency": { - "description": "The extent to which the incident resolution can be delayed for ServiceNow ITSM connectors.", - "type": "string" - } - }, - "example": null - }, - "id": { - "description": "The identifier for the connector. To create a case without a connector, use `none`.", - "type": "string", - "example": "none" - }, - "name": { - "description": "The name of the connector. To create a case without a connector, use `none`.", - "type": "string", - "example": "none" - }, - "type": { - "$ref": "#/components/schemas/connector_types" - } - }, - "required": [ - "fields", - "id", - "name", - "type" - ] - }, - "description": { - "description": "The description for the case.", - "type": "string" - }, - "owner": { - "$ref": "#/components/schemas/owners" - }, - "settings": { - "description": "An object that contains the case settings.", - "type": "object", - "properties": { - "syncAlerts": { - "description": "Turns alert syncing on or off.", - "type": "boolean" - } - } - }, - "severity": { - "$ref": "#/components/schemas/severity_property" - }, - "tags": { - "description": "The words and phrases that help categorize cases. It can be an empty array.", - "type": "array", - "items": { - "type": "string" - } - }, - "title": { - "description": "A title for the case.", - "type": "string" - } - }, - "required": [ - "connector", - "description", - "owner", - "settings", - "tags", - "title" - ] - }, - "examples": { - "createCaseRequest": { - "$ref": "#/components/examples/create_case_request" - } - } - } - } - }, - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json; charset=utf-8": { - "schema": { - "type": "object", - "properties": { - "closed_at": { - "type": "string", - "format": "date-time", - "nullable": true, - "example": null + "type": "object", + "properties": { + "closed_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": null }, "closed_by": { "type": "object", @@ -3939,8 +3687,8 @@ } }, "examples": { - "createCaseResponse": { - "$ref": "#/components/examples/create_case_response" + "updateCaseCommentResponse": { + "$ref": "#/components/examples/update_comment_response" } } } @@ -3953,9 +3701,60 @@ } ] }, + "get": { + "summary": "Retrieves all the comments from a case in the default space.", + "operationId": "getAllCaseCommentsDefaultSpace", + "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.\n", + "tags": [ + "cases", + "kibana" + ], + "deprecated": true, + "parameters": [ + { + "$ref": "#/components/parameters/case_id" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/alert_comment_response_properties" + }, + { + "$ref": "#/components/schemas/user_comment_response_properties" + } + ] + } + } + }, + "examples": {} + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/api/cases/{caseId}/comments/{commentId}": { "delete": { - "summary": "Deletes one or more cases.", - "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're deleting.\n", + "summary": "Deletes a comment or alert from a case in the default space.", + "operationId": "deleteCaseCommentDefaultSpace", + "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're deleting.\n", "tags": [ "cases", "kibana" @@ -3965,17 +3764,10 @@ "$ref": "#/components/parameters/kbn_xsrf" }, { - "$ref": "#/components/parameters/space_id" + "$ref": "#/components/parameters/case_id" }, { - "name": "ids", - "description": "The cases that you want to removed. All non-ASCII characters must be URL encoded.", - "in": "query", - "required": true, - "schema": { - "type": "string" - }, - "example": "d4e7abb0-b462-11ec-9a8d-698504725a43" + "$ref": "#/components/parameters/comment_id" } ], "responses": { @@ -3989,63 +3781,611 @@ } ] }, - "patch": { - "summary": "Updates one or more cases.", - "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're updating.\n", + "get": { + "summary": "Retrieves a comment from a case in the default space.", + "operationId": "getCaseCommentDefaultSpace", + "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.\n", "tags": [ "cases", "kibana" ], "parameters": [ { - "$ref": "#/components/parameters/kbn_xsrf" + "$ref": "#/components/parameters/case_id" }, { - "$ref": "#/components/parameters/space_id" + "$ref": "#/components/parameters/comment_id" } ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "cases": { - "type": "array", - "items": { - "type": "object", - "properties": { - "connector": { - "description": "An object that contains the connector configuration.", - "type": "object", - "properties": { - "fields": { - "description": "An object containing the connector fields. To create a case without a connector, specify null. If you want to omit any individual field, specify null as its value.", - "nullable": true, - "type": "object", - "properties": { - "caseId": { - "description": "The case identifier for Swimlane connectors.", - "type": "string" - }, - "category": { - "description": "The category of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.", - "type": "string" - }, - "destIp": { - "description": "A comma-separated list of destination IPs for ServiceNow SecOps connectors.", - "type": "string" - }, - "impact": { - "description": "The effect an incident had on business for ServiceNow ITSM connectors.", - "type": "string" - }, - "issueType": { - "description": "The type of issue for Jira connectors.", - "type": "string" - }, - "issueTypes": { - "description": "The type of incident for IBM Resilient connectors.", + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json; charset=utf-8": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/alert_comment_response_properties" + }, + { + "$ref": "#/components/schemas/user_comment_response_properties" + } + ] + }, + "examples": { + "getCaseCommentResponse": { + "$ref": "#/components/examples/get_comment_response" + } + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/s/{spaceId}/api/cases": { + "post": { + "summary": "Creates a case.", + "operationId": "createCase", + "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're creating.\n", + "tags": [ + "cases", + "kibana" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "connector": { + "description": "An object that contains the connector configuration.", + "type": "object", + "properties": { + "fields": { + "description": "An object containing the connector fields. To create a case without a connector, specify null. If you want to omit any individual field, specify null as its value.", + "nullable": true, + "type": "object", + "properties": { + "caseId": { + "description": "The case identifier for Swimlane connectors.", + "type": "string" + }, + "category": { + "description": "The category of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.", + "type": "string" + }, + "destIp": { + "description": "A comma-separated list of destination IPs for ServiceNow SecOps connectors.", + "type": "string" + }, + "impact": { + "description": "The effect an incident had on business for ServiceNow ITSM connectors.", + "type": "string" + }, + "issueType": { + "description": "The type of issue for Jira connectors.", + "type": "string" + }, + "issueTypes": { + "description": "The type of incident for IBM Resilient connectors.", + "type": "array", + "items": { + "type": "number" + } + }, + "malwareHash": { + "description": "A comma-separated list of malware hashes for ServiceNow SecOps connectors.", + "type": "string" + }, + "malwareUrl": { + "description": "A comma-separated list of malware URLs for ServiceNow SecOps connectors.", + "type": "string" + }, + "parent": { + "description": "The key of the parent issue, when the issue type is sub-task for Jira connectors.", + "type": "string" + }, + "priority": { + "description": "The priority of the issue for Jira and ServiceNow SecOps connectors.", + "type": "string" + }, + "severity": { + "description": "The severity of the incident for ServiceNow ITSM connectors.", + "type": "string" + }, + "severityCode": { + "description": "The severity code of the incident for IBM Resilient connectors.", + "type": "number" + }, + "sourceIp": { + "description": "A comma-separated list of source IPs for ServiceNow SecOps connectors.", + "type": "string" + }, + "subcategory": { + "description": "The subcategory of the incident for ServiceNow ITSM connectors.", + "type": "string" + }, + "urgency": { + "description": "The extent to which the incident resolution can be delayed for ServiceNow ITSM connectors.", + "type": "string" + } + }, + "example": null + }, + "id": { + "description": "The identifier for the connector. To create a case without a connector, use `none`.", + "type": "string", + "example": "none" + }, + "name": { + "description": "The name of the connector. To create a case without a connector, use `none`.", + "type": "string", + "example": "none" + }, + "type": { + "$ref": "#/components/schemas/connector_types" + } + }, + "required": [ + "fields", + "id", + "name", + "type" + ] + }, + "description": { + "description": "The description for the case.", + "type": "string" + }, + "owner": { + "$ref": "#/components/schemas/owners" + }, + "settings": { + "description": "An object that contains the case settings.", + "type": "object", + "properties": { + "syncAlerts": { + "description": "Turns alert syncing on or off.", + "type": "boolean" + } + } + }, + "severity": { + "$ref": "#/components/schemas/severity_property" + }, + "tags": { + "description": "The words and phrases that help categorize cases. It can be an empty array.", + "type": "array", + "items": { + "type": "string" + } + }, + "title": { + "description": "A title for the case.", + "type": "string" + } + }, + "required": [ + "connector", + "description", + "owner", + "settings", + "tags", + "title" + ] + }, + "examples": { + "createCaseRequest": { + "$ref": "#/components/examples/create_case_request" + } + } + } + } + }, + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "closed_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": null + }, + "closed_by": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "nullable": true, + "example": null + }, + "comments": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/alert_comment_response_properties" + }, + { + "$ref": "#/components/schemas/user_comment_response_properties" + } + ] + }, + "example": [] + }, + "connector": { + "type": "object", + "properties": { + "fields": { + "description": "An object containing the connector fields. To create a case without a connector, specify null. If you want to omit any individual field, specify null as its value.", + "nullable": true, + "type": "object", + "properties": { + "caseId": { + "description": "The case identifier for Swimlane connectors.", + "type": "string" + }, + "category": { + "description": "The category of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.", + "type": "string" + }, + "destIp": { + "description": "A comma-separated list of destination IPs for ServiceNow SecOps connectors.", + "type": "string" + }, + "impact": { + "description": "The effect an incident had on business for ServiceNow ITSM connectors.", + "type": "string" + }, + "issueType": { + "description": "The type of issue for Jira connectors.", + "type": "string" + }, + "issueTypes": { + "description": "The type of incident for IBM Resilient connectors.", + "type": "array", + "items": { + "type": "number" + } + }, + "malwareHash": { + "description": "A comma-separated list of malware hashes for ServiceNow SecOps connectors.", + "type": "string" + }, + "malwareUrl": { + "description": "A comma-separated list of malware URLs for ServiceNow SecOps connectors.", + "type": "string" + }, + "parent": { + "description": "The key of the parent issue, when the issue type is sub-task for Jira connectors.", + "type": "string" + }, + "priority": { + "description": "The priority of the issue for Jira and ServiceNow SecOps connectors.", + "type": "string" + }, + "severity": { + "description": "The severity of the incident for ServiceNow ITSM connectors.", + "type": "string" + }, + "severityCode": { + "description": "The severity code of the incident for IBM Resilient connectors.", + "type": "number" + }, + "sourceIp": { + "description": "A comma-separated list of source IPs for ServiceNow SecOps connectors.", + "type": "string" + }, + "subcategory": { + "description": "The subcategory of the incident for ServiceNow ITSM connectors.", + "type": "string" + }, + "urgency": { + "description": "The extent to which the incident resolution can be delayed for ServiceNow ITSM connectors.", + "type": "string" + } + }, + "example": null + }, + "id": { + "description": "The identifier for the connector. To create a case without a connector, use `none`.", + "type": "string", + "example": "none" + }, + "name": { + "description": "The name of the connector. To create a case without a connector, use `none`.", + "type": "string", + "example": "none" + }, + "type": { + "$ref": "#/components/schemas/connector_types" + } + } + }, + "created_at": { + "type": "string", + "format": "date-time", + "example": "2022-05-13T09:16:17.416Z" + }, + "created_by": { + "type": "object", + "properties": { + "email": { + "type": "string", + "example": null + }, + "full_name": { + "type": "string", + "example": null + }, + "username": { + "type": "string", + "example": "elastic" + } + } + }, + "description": { + "type": "string", + "example": "A case description." + }, + "duration": { + "type": "integer", + "description": "The elapsed time from the creation of the case to its closure (in seconds). If the case has not been closed, the duration is set to null. If the case was closed after less than half a second, the duration is rounded down to zero.\n", + "example": 120 + }, + "external_service": { + "type": "object", + "properties": { + "connector_id": { + "type": "string" + }, + "connector_name": { + "type": "string" + }, + "external_id": { + "type": "string" + }, + "external_title": { + "type": "string" + }, + "external_url": { + "type": "string" + }, + "pushed_at": { + "type": "string", + "format": "date-time" + }, + "pushed_by": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "nullable": true, + "example": null + } + } + }, + "id": { + "type": "string", + "example": "66b9aa00-94fa-11ea-9f74-e7e108796192" + }, + "owner": { + "$ref": "#/components/schemas/owners" + }, + "settings": { + "type": "object", + "properties": { + "syncAlerts": { + "type": "boolean", + "example": true + } + } + }, + "severity": { + "$ref": "#/components/schemas/severity_property" + }, + "status": { + "$ref": "#/components/schemas/status" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "example": [ + "tag-1" + ] + }, + "title": { + "type": "string", + "example": "Case title 1" + }, + "totalAlerts": { + "type": "integer", + "example": 0 + }, + "totalComment": { + "type": "integer", + "example": 0 + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": null + }, + "updated_by": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "nullable": true, + "example": null + }, + "version": { + "type": "string", + "example": "WzUzMiwxXQ==" + } + } + }, + "examples": { + "createCaseResponse": { + "$ref": "#/components/examples/create_case_response" + } + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "delete": { + "summary": "Deletes one or more cases.", + "operationId": "deleteCase", + "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're deleting.\n", + "tags": [ + "cases", + "kibana" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/space_id" + }, + { + "name": "ids", + "description": "The cases that you want to removed. All non-ASCII characters must be URL encoded.", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "example": "d4e7abb0-b462-11ec-9a8d-698504725a43" + } + ], + "responses": { + "204": { + "description": "Indicates a successful call." + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "patch": { + "summary": "Updates one or more cases.", + "operationId": "updateCase", + "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're updating.\n", + "tags": [ + "cases", + "kibana" + ], + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + }, + { + "$ref": "#/components/parameters/space_id" + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "cases": { + "type": "array", + "items": { + "type": "object", + "properties": { + "connector": { + "description": "An object that contains the connector configuration.", + "type": "object", + "properties": { + "fields": { + "description": "An object containing the connector fields. To create a case without a connector, specify null. If you want to omit any individual field, specify null as its value.", + "nullable": true, + "type": "object", + "properties": { + "caseId": { + "description": "The case identifier for Swimlane connectors.", + "type": "string" + }, + "category": { + "description": "The category of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.", + "type": "string" + }, + "destIp": { + "description": "A comma-separated list of destination IPs for ServiceNow SecOps connectors.", + "type": "string" + }, + "impact": { + "description": "The effect an incident had on business for ServiceNow ITSM connectors.", + "type": "string" + }, + "issueType": { + "description": "The type of issue for Jira connectors.", + "type": "string" + }, + "issueTypes": { + "description": "The type of incident for IBM Resilient connectors.", "type": "array", "items": { "type": "number" @@ -4466,6 +4806,7 @@ "/s/{spaceId}/api/cases/_find": { "get": { "summary": "Retrieves a paginated subset of cases.", + "operationId": "getCases", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", "tags": [ "cases", @@ -4972,6 +5313,7 @@ "/s/{spaceId}/api/cases/alerts/{alertId}": { "get": { "summary": "Returns the cases associated with a specific alert.", + "operationId": "getCasesByAlert", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", "x-technical-preview": true, "tags": [ @@ -5035,6 +5377,7 @@ "/s/{spaceId}/api/cases/configure": { "get": { "summary": "Retrieves external connection details, such as the closure type and default connector for cases.", + "operationId": "getCaseConfiguration", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case configuration.\n", "tags": [ "cases", @@ -5246,6 +5589,7 @@ }, "post": { "summary": "Sets external connection details, such as the closure type and default connector for cases.", + "operationId": "setCaseConfiguration", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case configuration. Connectors are used to interface with external systems. You must create a connector before you can use it in your cases. Refer to the add connectors API. If you set a default connector, it is automatically selected when you create cases in Kibana. If you use the create case API, however, you must still specify all of the connector details.\n", "tags": [ "cases", @@ -5596,6 +5940,7 @@ "/s/{spaceId}/api/cases/configure/{configurationId}": { "patch": { "summary": "Updates external connection details, such as the closure type and default connector for cases.", + "operationId": "updateCaseConfiguration", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case configuration. Connectors are used to interface with external systems. You must create a connector before you can use it in your cases. Refer to the add connectors API.\n", "tags": [ "cases", @@ -5935,6 +6280,7 @@ "/s/{spaceId}/api/cases/configure/connectors/_find": { "get": { "summary": "Retrieves information about connectors.", + "operationId": "getCaseConnectors", "description": "In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "cases", @@ -5953,47 +6299,228 @@ "schema": { "type": "array", "items": { - "type": "object", - "properties": { - "actionTypeId": { - "$ref": "#/components/schemas/connector_types" - }, - "config": { - "type": "object", - "properties": { - "apiUrl": { - "type": "string" - }, - "projectKey": { - "type": "string" - } - }, - "additionalProperties": true - }, - "id": { - "type": "string" - }, - "isDeprecated": { - "type": "boolean" - }, - "isMissingSecrets": { - "type": "boolean" - }, - "isPreconfigured": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "referencedByCount": { - "type": "integer" - } - } + "type": "object", + "properties": { + "actionTypeId": { + "$ref": "#/components/schemas/connector_types" + }, + "config": { + "type": "object", + "properties": { + "apiUrl": { + "type": "string" + }, + "projectKey": { + "type": "string" + } + }, + "additionalProperties": true + }, + "id": { + "type": "string" + }, + "isDeprecated": { + "type": "boolean" + }, + "isMissingSecrets": { + "type": "boolean" + }, + "isPreconfigured": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "referencedByCount": { + "type": "integer" + } + } + } + }, + "examples": { + "findConnectorResponse": { + "$ref": "#/components/examples/find_connector_response" + } + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/s/{spaceId}/api/cases/reporters": { + "get": { + "summary": "Returns information about the users who opened cases.", + "operationId": "getCaseReporters", + "description": "You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases. The API returns information about the users as they existed at the time of the case creation, including their name, full name, and email address. If any of those details change thereafter or if a user is deleted, the information returned by this API is unchanged.\n", + "tags": [ + "cases", + "kibana" + ], + "parameters": [ + { + "$ref": "#/components/parameters/space_id" + }, + { + "$ref": "#/components/parameters/owner" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "username": { + "type": "string" + } + } + } + }, + "examples": { + "getReportersResponse": { + "$ref": "#/components/examples/get_reporters_response" + } + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/s/{spaceId}/api/cases/status": { + "get": { + "summary": "Returns the number of cases that are open, closed, and in progress.", + "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", + "deprecated": true, + "tags": [ + "cases", + "kibana" + ], + "parameters": [ + { + "$ref": "#/components/parameters/space_id" + }, + { + "$ref": "#/components/parameters/owner" + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "count_closed_cases": { + "type": "integer" + }, + "count_in_progress_cases": { + "type": "integer" + }, + "count_open_cases": { + "type": "integer" + } + } + }, + "examples": { + "getStatusResponse": { + "$ref": "#/components/examples/get_status_response" + } + } + } + } + } + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "servers": [ + { + "url": "https://localhost:5601" + } + ] + }, + "/s/{spaceId}/api/cases/tags": { + "get": { + "summary": "Aggregates and returns a list of case tags.", + "operationId": "getCaseTags", + "description": "You must have read privileges for the **Cases*** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", + "tags": [ + "cases", + "kibana" + ], + "parameters": [ + { + "$ref": "#/components/parameters/space_id" + }, + { + "in": "query", + "name": "owner", + "description": "A filter to limit the retrieved case statistics to a specific set of applications. If this parameter is omitted, the response contains tags from all cases that the user has access to read.", + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/owners" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/owners" + } + } + ] + } + } + ], + "responses": { + "200": { + "description": "Indicates a successful call.", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "array", + "items": { + "type": "string" } }, "examples": { - "findConnectorResponse": { - "$ref": "#/components/examples/find_connector_response" + "getTagsResponse": { + "$ref": "#/components/examples/get_tags_response" } } } @@ -6012,20 +6539,31 @@ } ] }, - "/s/{spaceId}/api/cases/reporters": { + "/s/{spaceId}/api/cases/{caseId}": { "get": { - "summary": "Returns information about the users who opened cases.", - "description": "You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases. The API returns information about the users as they existed at the time of the case creation, including their name, full name, and email address. If any of those details change thereafter or if a user is deleted, the information returned by this API is unchanged.\n", + "summary": "Retrieves information about a case.", + "operationId": "getCase", + "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking.\n", "tags": [ "cases", "kibana" ], "parameters": [ + { + "$ref": "#/components/parameters/case_id" + }, { "$ref": "#/components/parameters/space_id" }, { - "$ref": "#/components/parameters/owner" + "in": "query", + "name": "includeComments", + "description": "Determines whether case comments are returned.", + "deprecated": true, + "schema": { + "type": "boolean", + "default": true + } } ], "responses": { @@ -6034,145 +6572,278 @@ "content": { "application/json; charset=utf-8": { "schema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "email": { - "type": "string" + "type": "object", + "properties": { + "closed_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": null + }, + "closed_by": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "username": { + "type": "string" + } }, - "full_name": { + "nullable": true, + "example": null + }, + "comments": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/alert_comment_response_properties" + }, + { + "$ref": "#/components/schemas/user_comment_response_properties" + } + ] + }, + "example": [] + }, + "connector": { + "type": "object", + "properties": { + "fields": { + "description": "An object containing the connector fields. To create a case without a connector, specify null. If you want to omit any individual field, specify null as its value.", + "nullable": true, + "type": "object", + "properties": { + "caseId": { + "description": "The case identifier for Swimlane connectors.", + "type": "string" + }, + "category": { + "description": "The category of the incident for ServiceNow ITSM and ServiceNow SecOps connectors.", + "type": "string" + }, + "destIp": { + "description": "A comma-separated list of destination IPs for ServiceNow SecOps connectors.", + "type": "string" + }, + "impact": { + "description": "The effect an incident had on business for ServiceNow ITSM connectors.", + "type": "string" + }, + "issueType": { + "description": "The type of issue for Jira connectors.", + "type": "string" + }, + "issueTypes": { + "description": "The type of incident for IBM Resilient connectors.", + "type": "array", + "items": { + "type": "number" + } + }, + "malwareHash": { + "description": "A comma-separated list of malware hashes for ServiceNow SecOps connectors.", + "type": "string" + }, + "malwareUrl": { + "description": "A comma-separated list of malware URLs for ServiceNow SecOps connectors.", + "type": "string" + }, + "parent": { + "description": "The key of the parent issue, when the issue type is sub-task for Jira connectors.", + "type": "string" + }, + "priority": { + "description": "The priority of the issue for Jira and ServiceNow SecOps connectors.", + "type": "string" + }, + "severity": { + "description": "The severity of the incident for ServiceNow ITSM connectors.", + "type": "string" + }, + "severityCode": { + "description": "The severity code of the incident for IBM Resilient connectors.", + "type": "number" + }, + "sourceIp": { + "description": "A comma-separated list of source IPs for ServiceNow SecOps connectors.", + "type": "string" + }, + "subcategory": { + "description": "The subcategory of the incident for ServiceNow ITSM connectors.", + "type": "string" + }, + "urgency": { + "description": "The extent to which the incident resolution can be delayed for ServiceNow ITSM connectors.", + "type": "string" + } + }, + "example": null + }, + "id": { + "description": "The identifier for the connector. To create a case without a connector, use `none`.", + "type": "string", + "example": "none" + }, + "name": { + "description": "The name of the connector. To create a case without a connector, use `none`.", + "type": "string", + "example": "none" + }, + "type": { + "$ref": "#/components/schemas/connector_types" + } + } + }, + "created_at": { + "type": "string", + "format": "date-time", + "example": "2022-05-13T09:16:17.416Z" + }, + "created_by": { + "type": "object", + "properties": { + "email": { + "type": "string", + "example": null + }, + "full_name": { + "type": "string", + "example": null + }, + "username": { + "type": "string", + "example": "elastic" + } + } + }, + "description": { + "type": "string", + "example": "A case description." + }, + "duration": { + "type": "integer", + "description": "The elapsed time from the creation of the case to its closure (in seconds). If the case has not been closed, the duration is set to null. If the case was closed after less than half a second, the duration is rounded down to zero.\n", + "example": 120 + }, + "external_service": { + "type": "object", + "properties": { + "connector_id": { + "type": "string" + }, + "connector_name": { + "type": "string" + }, + "external_id": { + "type": "string" + }, + "external_title": { + "type": "string" + }, + "external_url": { + "type": "string" + }, + "pushed_at": { + "type": "string", + "format": "date-time" + }, + "pushed_by": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "nullable": true, + "example": null + } + } + }, + "id": { + "type": "string", + "example": "66b9aa00-94fa-11ea-9f74-e7e108796192" + }, + "owner": { + "$ref": "#/components/schemas/owners" + }, + "settings": { + "type": "object", + "properties": { + "syncAlerts": { + "type": "boolean", + "example": true + } + } + }, + "severity": { + "$ref": "#/components/schemas/severity_property" + }, + "status": { + "$ref": "#/components/schemas/status" + }, + "tags": { + "type": "array", + "items": { "type": "string" }, - "username": { - "type": "string" - } - } - } - }, - "examples": { - "getReportersResponse": { - "$ref": "#/components/examples/get_reporters_response" - } - } - } - } - } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "/s/{spaceId}/api/cases/status": { - "get": { - "summary": "Returns the number of cases that are open, closed, and in progress.", - "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", - "deprecated": true, - "tags": [ - "cases", - "kibana" - ], - "parameters": [ - { - "$ref": "#/components/parameters/space_id" - }, - { - "$ref": "#/components/parameters/owner" - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json; charset=utf-8": { - "schema": { - "type": "object", - "properties": { - "count_closed_cases": { - "type": "integer" + "example": [ + "tag-1" + ] }, - "count_in_progress_cases": { - "type": "integer" + "title": { + "type": "string", + "example": "Case title 1" }, - "count_open_cases": { - "type": "integer" + "totalAlerts": { + "type": "integer", + "example": 0 + }, + "totalComment": { + "type": "integer", + "example": 0 + }, + "updated_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": null + }, + "updated_by": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "full_name": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "nullable": true, + "example": null + }, + "version": { + "type": "string", + "example": "WzUzMiwxXQ==" } } }, "examples": { - "getStatusResponse": { - "$ref": "#/components/examples/get_status_response" - } - } - } - } - } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "/s/{spaceId}/api/cases/tags": { - "get": { - "summary": "Aggregates and returns a list of case tags.", - "description": "You must have read privileges for the **Cases*** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", - "tags": [ - "cases", - "kibana" - ], - "parameters": [ - { - "$ref": "#/components/parameters/space_id" - }, - { - "in": "query", - "name": "owner", - "description": "A filter to limit the retrieved case statistics to a specific set of applications. If this parameter is omitted, the response contains tags from all cases that the user has access to read.", - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/owners" - }, - { - "type": "array", - "items": { - "$ref": "#/components/schemas/owners" - } - } - ] - } - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json; charset=utf-8": { - "schema": { - "type": "array", - "items": { - "type": "string" - } - }, - "examples": { - "getTagsResponse": { - "$ref": "#/components/examples/get_tags_response" + "getCaseResponse": { + "$ref": "#/components/examples/get_case_response" } } } @@ -6194,6 +6865,7 @@ "/s/{spaceId}/api/cases/{caseId}/comments": { "post": { "summary": "Adds a comment or alert to a case.", + "operationId": "addCaseComment", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're creating.\n", "tags": [ "cases", @@ -6523,6 +7195,7 @@ }, "delete": { "summary": "Deletes all comments and alerts from a case.", + "operationId": "deleteCaseComments", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're deleting.\n", "tags": [ "cases", @@ -6552,6 +7225,7 @@ }, "patch": { "summary": "Updates a comment or alert in a case.", + "operationId": "updateCaseComment", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're updating. NOTE: You cannot change the comment type or the owner of a comment.\n", "tags": [ "cases", @@ -6881,6 +7555,7 @@ }, "get": { "summary": "Retrieves all the comments from a case.", + "operationId": "getAllCaseComments", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.\n", "deprecated": true, "tags": [ @@ -6933,6 +7608,7 @@ "/s/{spaceId}/api/cases/{caseId}/comments/{commentId}": { "delete": { "summary": "Deletes a comment or alert from a case.", + "operationId": "deleteCaseComment", "description": "You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're deleting.\n", "tags": [ "cases", @@ -6965,6 +7641,7 @@ }, "get": { "summary": "Retrieves a comment from a case.", + "operationId": "getCaseComment", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security*** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.\n", "tags": [ "cases", @@ -7823,6 +8500,67 @@ "tag 2" ] }, + "get_case_response": { + "summary": "Retrieves information about a case including its comments.", + "value": { + "id": "31cdada0-02c1-11ed-85f2-4f7c222ca2fa", + "version": "WzM2LDFd", + "comments": [ + { + "id": "2134c1d0-02c2-11ed-85f2-4f7c222ca2fa", + "version": "WzM3LDFd", + "type": "user", + "owner": "cases", + "comment": "A new comment", + "created_at": "2022-07-13T15:40:32.335Z", + "created_by": { + "email": null, + "full_name": null, + "username": "elastic" + }, + "pushed_at": null, + "pushed_by": null, + "updated_at": null, + "updated_by": null + } + ], + "totalComment": 1, + "totalAlerts": 0, + "title": "Case title 1", + "tags": [ + "tag 1" + ], + "settings": { + "syncAlerts": true + }, + "owner": "cases", + "description": "A case description", + "duration": null, + "severity": "low", + "closed_at": null, + "closed_by": null, + "created_at": "2022-07-13T15:33:50.604Z", + "created_by": { + "username": "elastic", + "email": null, + "full_name": null + }, + "status": "open", + "updated_at": "2022-07-13T15:40:32.335Z", + "updated_by": { + "full_name": null, + "email": null, + "username": "elastic" + }, + "connector": { + "id": "none", + "name": "none", + "type": ".none", + "fields": null + }, + "external_service": null + } + }, "add_comment_request": { "summary": "Adds a comment to a case.", "value": { diff --git a/x-pack/plugins/cases/docs/openapi/bundled.yaml b/x-pack/plugins/cases/docs/openapi/bundled.yaml index 21622619dbbe7..57b01b3f05365 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.yaml +++ b/x-pack/plugins/cases/docs/openapi/bundled.yaml @@ -19,7 +19,8 @@ servers: paths: /api/cases: post: - summary: Creates a case. + summary: Creates a case in the default space. + operationId: createCaseDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -411,7 +412,8 @@ paths: servers: - url: https://localhost:5601 delete: - summary: Deletes one or more cases. + summary: Deletes one or more cases from the default space. + operationId: deleteCaseDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -436,7 +438,8 @@ paths: servers: - url: https://localhost:5601 patch: - summary: Updates one or more cases. + summary: Updates one or more cases in the default space. + operationId: updateCaseDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -839,7 +842,8 @@ paths: - url: https://localhost:5601 /api/cases/_find: get: - summary: Retrieves a paginated subset of cases. + summary: Retrieves a paginated subset of cases from the default space. + operationId: getCasesDefaultSpace description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -1230,7 +1234,8 @@ paths: - url: https://localhost:5601 /api/cases/alerts/{alertId}: get: - summary: Returns the cases associated with a specific alert. + summary: Returns the cases associated with a specific alert in the default space. + operationId: getCasesByAlertDefaultSpace description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -1269,7 +1274,8 @@ paths: get: summary: >- Retrieves external connection details, such as the closure type and - default connector for cases. + default connector for cases in the default space. + operationId: getCaseConfigurationDefaultSpace description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -1455,7 +1461,8 @@ paths: post: summary: >- Sets external connection details, such as the closure type and default - connector for cases. + connector for cases in the default space. + operationId: setCaseConfigurationDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -1776,7 +1783,8 @@ paths: patch: summary: >- Updates external connection details, such as the closure type and - default connector for cases. + default connector for cases in the default space. + operationId: updateCaseConfigurationDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -2086,7 +2094,8 @@ paths: - url: https://localhost:5601 /api/cases/configure/connectors/_find: get: - summary: Retrieves information about connectors. + summary: Retrieves information about connectors for cases in the default space. + operationId: getCaseConnectorsDefaultSpace description: > In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and @@ -2136,7 +2145,10 @@ paths: - url: https://localhost:5601 /api/cases/reporters: get: - summary: Returns information about the users who opened cases. + summary: >- + Returns information about the users who opened cases in the default + space. + operationId: getCaseReportersDefaultCase description: > You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -2209,7 +2221,8 @@ paths: - url: https://localhost:5601 /api/cases/tags: get: - summary: Aggregates and returns a list of case tags. + summary: Aggregates and returns a list of case tags in the default space. + operationId: getCaseTagsDefaultSpace description: > You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -2246,29 +2259,26 @@ paths: - url: https://localhost:5601 servers: - url: https://localhost:5601 - /api/cases/{caseId}/comments: - post: - summary: Adds a comment or alert to a case. + /api/cases/{caseId}: + get: + summary: Retrieves information about a case in the default space. + operationId: getCaseDefaultSpace description: > - You must have `all` privileges for the **Cases** feature in the + You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana - feature privileges, depending on the owner of the case you're creating. + feature privileges, depending on the owner of the case you're seeking. tags: - cases - kibana parameters: - - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/case_id' - requestBody: - content: - application/json: - schema: - oneOf: - - $ref: '#/components/schemas/add_alert_comment_request_properties' - - $ref: '#/components/schemas/add_user_comment_request_properties' - examples: - createCaseCommentRequest: - $ref: '#/components/examples/add_comment_request' + - in: query + name: includeComments + description: Determines whether case comments are returned. + deprecated: true + schema: + type: boolean + default: true responses: '200': description: Indicates a successful call. @@ -2503,34 +2513,20 @@ paths: type: string example: WzUzMiwxXQ== examples: - createCaseCommentResponse: - $ref: '#/components/examples/add_comment_response' - servers: - - url: https://localhost:5601 - delete: - summary: Deletes all comments and alerts from a case. - description: > - You must have `all` privileges for the **Cases** feature in the - **Management**, **Observability**, or **Security** section of the Kibana - feature privileges, depending on the owner of the cases you're deleting. - tags: - - cases - - kibana - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - $ref: '#/components/parameters/case_id' - responses: - '204': - description: Indicates a successful call. + getCaseResponse: + $ref: '#/components/examples/get_case_response' servers: - url: https://localhost:5601 - patch: - summary: Updates a comment or alert in a case. + servers: + - url: https://localhost:5601 + /api/cases/{caseId}/comments: + post: + summary: Adds a comment or alert to a case in the default space. + operationId: addCaseCommentDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana - feature privileges, depending on the owner of the case you're updating. - NOTE: You cannot change the comment type or the owner of a comment. + feature privileges, depending on the owner of the case you're creating. tags: - cases - kibana @@ -2542,11 +2538,11 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/update_alert_comment_request_properties' - - $ref: '#/components/schemas/update_user_comment_request_properties' + - $ref: '#/components/schemas/add_alert_comment_request_properties' + - $ref: '#/components/schemas/add_user_comment_request_properties' examples: - updateCaseCommentRequest: - $ref: '#/components/examples/update_comment_request' + createCaseCommentRequest: + $ref: '#/components/examples/add_comment_request' responses: '200': description: Indicates a successful call. @@ -2781,42 +2777,13 @@ paths: type: string example: WzUzMiwxXQ== examples: - updateCaseCommentResponse: - $ref: '#/components/examples/update_comment_response' - servers: - - url: https://localhost:5601 - get: - summary: Retrieves all the comments from a case. - description: > - You must have `read` privileges for the **Cases** feature in the - **Management**, **Observability**, or **Security** section of the Kibana - feature privileges, depending on the owner of the cases with the - comments you're seeking. - tags: - - cases - - kibana - deprecated: true - parameters: - - $ref: '#/components/parameters/case_id' - responses: - '200': - description: Indicates a successful call. - content: - application/json; charset=utf-8: - schema: - type: array - items: - anyOf: - - $ref: '#/components/schemas/alert_comment_response_properties' - - $ref: '#/components/schemas/user_comment_response_properties' - examples: {} + createCaseCommentResponse: + $ref: '#/components/examples/add_comment_response' servers: - url: https://localhost:5601 - servers: - - url: https://localhost:5601 - /api/cases/{caseId}/comments/{commentId}: delete: - summary: Deletes a comment or alert from a case. + summary: Deletes all comments and alerts from a case in the default space. + operationId: deleteCaseCommentsDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -2827,162 +2794,475 @@ paths: parameters: - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/case_id' - - $ref: '#/components/parameters/comment_id' responses: '204': description: Indicates a successful call. servers: - url: https://localhost:5601 - get: - summary: Retrieves a comment from a case. + patch: + summary: Updates a comment or alert in a case in the default space. + operationId: updateCaseCommentDefaultSpace description: > - You must have `read` privileges for the **Cases** feature in the + You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana - feature privileges, depending on the owner of the cases with the - comments you're seeking. + feature privileges, depending on the owner of the case you're updating. + NOTE: You cannot change the comment type or the owner of a comment. tags: - cases - kibana parameters: + - $ref: '#/components/parameters/kbn_xsrf' - $ref: '#/components/parameters/case_id' - - $ref: '#/components/parameters/comment_id' + requestBody: + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/update_alert_comment_request_properties' + - $ref: '#/components/schemas/update_user_comment_request_properties' + examples: + updateCaseCommentRequest: + $ref: '#/components/examples/update_comment_request' responses: '200': description: Indicates a successful call. content: application/json; charset=utf-8: schema: - oneOf: - - $ref: '#/components/schemas/alert_comment_response_properties' - - $ref: '#/components/schemas/user_comment_response_properties' - examples: - getCaseCommentResponse: - $ref: '#/components/examples/get_comment_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 - /s/{spaceId}/api/cases: - post: - summary: Creates a case. - description: > - You must have `all` privileges for the **Cases** feature in the - **Management**, **Observability**, or **Security** section of the - Kibana feature privileges, depending on the owner of the case you're - creating. - tags: - - cases - - kibana - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - $ref: '#/components/parameters/space_id' - requestBody: - content: - application/json: - schema: - type: object - properties: - connector: - description: An object that contains the connector configuration. - type: object - properties: - fields: - description: >- - An object containing the connector fields. To create a - case without a connector, specify null. If you want to - omit any individual field, specify null as its value. - nullable: true - type: object - properties: - caseId: - description: The case identifier for Swimlane connectors. - type: string - category: - description: >- - The category of the incident for ServiceNow ITSM and - ServiceNow SecOps connectors. - type: string - destIp: - description: >- - A comma-separated list of destination IPs for - ServiceNow SecOps connectors. - type: string - impact: - description: >- - The effect an incident had on business for - ServiceNow ITSM connectors. - type: string - issueType: - description: The type of issue for Jira connectors. - type: string - issueTypes: - description: The type of incident for IBM Resilient connectors. - type: array - items: - type: number - malwareHash: - description: >- - A comma-separated list of malware hashes for - ServiceNow SecOps connectors. - type: string - malwareUrl: - description: >- - A comma-separated list of malware URLs for - ServiceNow SecOps connectors. - type: string - parent: - description: >- - The key of the parent issue, when the issue type is - sub-task for Jira connectors. - type: string - priority: - description: >- - The priority of the issue for Jira and ServiceNow - SecOps connectors. - type: string - severity: - description: >- - The severity of the incident for ServiceNow ITSM - connectors. - type: string - severityCode: - description: >- - The severity code of the incident for IBM Resilient - connectors. - type: number - sourceIp: - description: >- - A comma-separated list of source IPs for ServiceNow - SecOps connectors. - type: string - subcategory: - description: >- - The subcategory of the incident for ServiceNow ITSM - connectors. - type: string - urgency: - description: >- - The extent to which the incident resolution can be - delayed for ServiceNow ITSM connectors. - type: string - example: null - id: - description: >- - The identifier for the connector. To create a case - without a connector, use `none`. - type: string - example: none - name: - description: >- - The name of the connector. To create a case without a - connector, use `none`. - type: string - example: none - type: - $ref: '#/components/schemas/connector_types' - required: - - fields - - id + type: object + properties: + closed_at: + type: string + format: date-time + nullable: true + example: null + closed_by: + type: object + properties: + email: + type: string + full_name: + type: string + username: + type: string + nullable: true + example: null + comments: + type: array + items: + oneOf: + - $ref: >- + #/components/schemas/alert_comment_response_properties + - $ref: >- + #/components/schemas/user_comment_response_properties + example: [] + connector: + type: object + properties: + fields: + description: >- + An object containing the connector fields. To create a + case without a connector, specify null. If you want to + omit any individual field, specify null as its value. + nullable: true + type: object + properties: + caseId: + description: The case identifier for Swimlane connectors. + type: string + category: + description: >- + The category of the incident for ServiceNow ITSM + and ServiceNow SecOps connectors. + type: string + destIp: + description: >- + A comma-separated list of destination IPs for + ServiceNow SecOps connectors. + type: string + impact: + description: >- + The effect an incident had on business for + ServiceNow ITSM connectors. + type: string + issueType: + description: The type of issue for Jira connectors. + type: string + issueTypes: + description: The type of incident for IBM Resilient connectors. + type: array + items: + type: number + malwareHash: + description: >- + A comma-separated list of malware hashes for + ServiceNow SecOps connectors. + type: string + malwareUrl: + description: >- + A comma-separated list of malware URLs for + ServiceNow SecOps connectors. + type: string + parent: + description: >- + The key of the parent issue, when the issue type + is sub-task for Jira connectors. + type: string + priority: + description: >- + The priority of the issue for Jira and ServiceNow + SecOps connectors. + type: string + severity: + description: >- + The severity of the incident for ServiceNow ITSM + connectors. + type: string + severityCode: + description: >- + The severity code of the incident for IBM + Resilient connectors. + type: number + sourceIp: + description: >- + A comma-separated list of source IPs for + ServiceNow SecOps connectors. + type: string + subcategory: + description: >- + The subcategory of the incident for ServiceNow + ITSM connectors. + type: string + urgency: + description: >- + The extent to which the incident resolution can be + delayed for ServiceNow ITSM connectors. + type: string + example: null + id: + description: >- + The identifier for the connector. To create a case + without a connector, use `none`. + type: string + example: none + name: + description: >- + The name of the connector. To create a case without a + connector, use `none`. + type: string + example: none + type: + $ref: '#/components/schemas/connector_types' + created_at: + type: string + format: date-time + example: '2022-05-13T09:16:17.416Z' + created_by: + type: object + properties: + email: + type: string + example: null + full_name: + type: string + example: null + username: + type: string + example: elastic + description: + type: string + example: A case description. + duration: + type: integer + description: > + The elapsed time from the creation of the case to its + closure (in seconds). If the case has not been closed, the + duration is set to null. If the case was closed after less + than half a second, the duration is rounded down to zero. + example: 120 + external_service: + type: object + properties: + connector_id: + type: string + connector_name: + type: string + external_id: + type: string + external_title: + type: string + external_url: + type: string + pushed_at: + type: string + format: date-time + pushed_by: + type: object + properties: + email: + type: string + full_name: + type: string + username: + type: string + nullable: true + example: null + id: + type: string + example: 66b9aa00-94fa-11ea-9f74-e7e108796192 + owner: + $ref: '#/components/schemas/owners' + settings: + type: object + properties: + syncAlerts: + type: boolean + example: true + severity: + $ref: '#/components/schemas/severity_property' + status: + $ref: '#/components/schemas/status' + tags: + type: array + items: + type: string + example: + - tag-1 + title: + type: string + example: Case title 1 + totalAlerts: + type: integer + example: 0 + totalComment: + type: integer + example: 0 + updated_at: + type: string + format: date-time + nullable: true + example: null + updated_by: + type: object + properties: + email: + type: string + full_name: + type: string + username: + type: string + nullable: true + example: null + version: + type: string + example: WzUzMiwxXQ== + examples: + updateCaseCommentResponse: + $ref: '#/components/examples/update_comment_response' + servers: + - url: https://localhost:5601 + get: + summary: Retrieves all the comments from a case in the default space. + operationId: getAllCaseCommentsDefaultSpace + description: > + You must have `read` privileges for the **Cases** feature in the + **Management**, **Observability**, or **Security** section of the Kibana + feature privileges, depending on the owner of the cases with the + comments you're seeking. + tags: + - cases + - kibana + deprecated: true + parameters: + - $ref: '#/components/parameters/case_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json; charset=utf-8: + schema: + type: array + items: + anyOf: + - $ref: '#/components/schemas/alert_comment_response_properties' + - $ref: '#/components/schemas/user_comment_response_properties' + examples: {} + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /api/cases/{caseId}/comments/{commentId}: + delete: + summary: Deletes a comment or alert from a case in the default space. + operationId: deleteCaseCommentDefaultSpace + description: > + You must have `all` privileges for the **Cases** feature in the + **Management**, **Observability**, or **Security** section of the Kibana + feature privileges, depending on the owner of the cases you're deleting. + tags: + - cases + - kibana + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/case_id' + - $ref: '#/components/parameters/comment_id' + responses: + '204': + description: Indicates a successful call. + servers: + - url: https://localhost:5601 + get: + summary: Retrieves a comment from a case in the default space. + operationId: getCaseCommentDefaultSpace + description: > + You must have `read` privileges for the **Cases** feature in the + **Management**, **Observability**, or **Security** section of the Kibana + feature privileges, depending on the owner of the cases with the + comments you're seeking. + tags: + - cases + - kibana + parameters: + - $ref: '#/components/parameters/case_id' + - $ref: '#/components/parameters/comment_id' + responses: + '200': + description: Indicates a successful call. + content: + application/json; charset=utf-8: + schema: + oneOf: + - $ref: '#/components/schemas/alert_comment_response_properties' + - $ref: '#/components/schemas/user_comment_response_properties' + examples: + getCaseCommentResponse: + $ref: '#/components/examples/get_comment_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /s/{spaceId}/api/cases: + post: + summary: Creates a case. + operationId: createCase + description: > + You must have `all` privileges for the **Cases** feature in the + **Management**, **Observability**, or **Security** section of the + Kibana feature privileges, depending on the owner of the case you're + creating. + tags: + - cases + - kibana + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + - $ref: '#/components/parameters/space_id' + requestBody: + content: + application/json: + schema: + type: object + properties: + connector: + description: An object that contains the connector configuration. + type: object + properties: + fields: + description: >- + An object containing the connector fields. To create a + case without a connector, specify null. If you want to + omit any individual field, specify null as its value. + nullable: true + type: object + properties: + caseId: + description: The case identifier for Swimlane connectors. + type: string + category: + description: >- + The category of the incident for ServiceNow ITSM and + ServiceNow SecOps connectors. + type: string + destIp: + description: >- + A comma-separated list of destination IPs for + ServiceNow SecOps connectors. + type: string + impact: + description: >- + The effect an incident had on business for + ServiceNow ITSM connectors. + type: string + issueType: + description: The type of issue for Jira connectors. + type: string + issueTypes: + description: The type of incident for IBM Resilient connectors. + type: array + items: + type: number + malwareHash: + description: >- + A comma-separated list of malware hashes for + ServiceNow SecOps connectors. + type: string + malwareUrl: + description: >- + A comma-separated list of malware URLs for + ServiceNow SecOps connectors. + type: string + parent: + description: >- + The key of the parent issue, when the issue type is + sub-task for Jira connectors. + type: string + priority: + description: >- + The priority of the issue for Jira and ServiceNow + SecOps connectors. + type: string + severity: + description: >- + The severity of the incident for ServiceNow ITSM + connectors. + type: string + severityCode: + description: >- + The severity code of the incident for IBM Resilient + connectors. + type: number + sourceIp: + description: >- + A comma-separated list of source IPs for ServiceNow + SecOps connectors. + type: string + subcategory: + description: >- + The subcategory of the incident for ServiceNow ITSM + connectors. + type: string + urgency: + description: >- + The extent to which the incident resolution can be + delayed for ServiceNow ITSM connectors. + type: string + example: null + id: + description: >- + The identifier for the connector. To create a case + without a connector, use `none`. + type: string + example: none + name: + description: >- + The name of the connector. To create a case without a + connector, use `none`. + type: string + example: none + type: + $ref: '#/components/schemas/connector_types' + required: + - fields + - id - name - type description: @@ -3259,6 +3539,7 @@ paths: - url: https://localhost:5601 delete: summary: Deletes one or more cases. + operationId: deleteCase description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the @@ -3286,6 +3567,7 @@ paths: - url: https://localhost:5601 patch: summary: Updates one or more cases. + operationId: updateCase description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the @@ -3691,6 +3973,7 @@ paths: /s/{spaceId}/api/cases/_find: get: summary: Retrieves a paginated subset of cases. + operationId: getCases description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -4085,6 +4368,7 @@ paths: /s/{spaceId}/api/cases/alerts/{alertId}: get: summary: Returns the cases associated with a specific alert. + operationId: getCasesByAlert description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -4125,6 +4409,7 @@ paths: summary: >- Retrieves external connection details, such as the closure type and default connector for cases. + operationId: getCaseConfiguration description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -4312,6 +4597,7 @@ paths: summary: >- Sets external connection details, such as the closure type and default connector for cases. + operationId: setCaseConfiguration description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -4634,6 +4920,7 @@ paths: summary: >- Updates external connection details, such as the closure type and default connector for cases. + operationId: updateCaseConfiguration description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -4945,6 +5232,7 @@ paths: /s/{spaceId}/api/cases/configure/connectors/_find: get: summary: Retrieves information about connectors. + operationId: getCaseConnectors description: > In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and @@ -4997,6 +5285,7 @@ paths: /s/{spaceId}/api/cases/reporters: get: summary: Returns information about the users who opened cases. + operationId: getCaseReporters description: > You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -5058,53 +5347,315 @@ paths: properties: count_closed_cases: type: integer - count_in_progress_cases: + count_in_progress_cases: + type: integer + count_open_cases: + type: integer + examples: + getStatusResponse: + $ref: '#/components/examples/get_status_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /s/{spaceId}/api/cases/tags: + get: + summary: Aggregates and returns a list of case tags. + operationId: getCaseTags + description: > + You must have read privileges for the **Cases*** feature in the + **Management**, **Observability**, or **Security** section of the Kibana + feature privileges, depending on the owner of the cases you're seeking. + tags: + - cases + - kibana + parameters: + - $ref: '#/components/parameters/space_id' + - in: query + name: owner + description: >- + A filter to limit the retrieved case statistics to a specific set of + applications. If this parameter is omitted, the response contains + tags from all cases that the user has access to read. + schema: + oneOf: + - $ref: '#/components/schemas/owners' + - type: array + items: + $ref: '#/components/schemas/owners' + responses: + '200': + description: Indicates a successful call. + content: + application/json; charset=utf-8: + schema: + type: array + items: + type: string + examples: + getTagsResponse: + $ref: '#/components/examples/get_tags_response' + servers: + - url: https://localhost:5601 + servers: + - url: https://localhost:5601 + /s/{spaceId}/api/cases/{caseId}: + get: + summary: Retrieves information about a case. + operationId: getCase + description: > + You must have `read` privileges for the **Cases** feature in the + **Management**, **Observability**, or **Security** section of the Kibana + feature privileges, depending on the owner of the case you're seeking. + tags: + - cases + - kibana + parameters: + - $ref: '#/components/parameters/case_id' + - $ref: '#/components/parameters/space_id' + - in: query + name: includeComments + description: Determines whether case comments are returned. + deprecated: true + schema: + type: boolean + default: true + responses: + '200': + description: Indicates a successful call. + content: + application/json; charset=utf-8: + schema: + type: object + properties: + closed_at: + type: string + format: date-time + nullable: true + example: null + closed_by: + type: object + properties: + email: + type: string + full_name: + type: string + username: + type: string + nullable: true + example: null + comments: + type: array + items: + oneOf: + - $ref: >- + #/components/schemas/alert_comment_response_properties + - $ref: >- + #/components/schemas/user_comment_response_properties + example: [] + connector: + type: object + properties: + fields: + description: >- + An object containing the connector fields. To create a + case without a connector, specify null. If you want to + omit any individual field, specify null as its value. + nullable: true + type: object + properties: + caseId: + description: The case identifier for Swimlane connectors. + type: string + category: + description: >- + The category of the incident for ServiceNow ITSM + and ServiceNow SecOps connectors. + type: string + destIp: + description: >- + A comma-separated list of destination IPs for + ServiceNow SecOps connectors. + type: string + impact: + description: >- + The effect an incident had on business for + ServiceNow ITSM connectors. + type: string + issueType: + description: The type of issue for Jira connectors. + type: string + issueTypes: + description: The type of incident for IBM Resilient connectors. + type: array + items: + type: number + malwareHash: + description: >- + A comma-separated list of malware hashes for + ServiceNow SecOps connectors. + type: string + malwareUrl: + description: >- + A comma-separated list of malware URLs for + ServiceNow SecOps connectors. + type: string + parent: + description: >- + The key of the parent issue, when the issue type + is sub-task for Jira connectors. + type: string + priority: + description: >- + The priority of the issue for Jira and ServiceNow + SecOps connectors. + type: string + severity: + description: >- + The severity of the incident for ServiceNow ITSM + connectors. + type: string + severityCode: + description: >- + The severity code of the incident for IBM + Resilient connectors. + type: number + sourceIp: + description: >- + A comma-separated list of source IPs for + ServiceNow SecOps connectors. + type: string + subcategory: + description: >- + The subcategory of the incident for ServiceNow + ITSM connectors. + type: string + urgency: + description: >- + The extent to which the incident resolution can be + delayed for ServiceNow ITSM connectors. + type: string + example: null + id: + description: >- + The identifier for the connector. To create a case + without a connector, use `none`. + type: string + example: none + name: + description: >- + The name of the connector. To create a case without a + connector, use `none`. + type: string + example: none + type: + $ref: '#/components/schemas/connector_types' + created_at: + type: string + format: date-time + example: '2022-05-13T09:16:17.416Z' + created_by: + type: object + properties: + email: + type: string + example: null + full_name: + type: string + example: null + username: + type: string + example: elastic + description: + type: string + example: A case description. + duration: + type: integer + description: > + The elapsed time from the creation of the case to its + closure (in seconds). If the case has not been closed, the + duration is set to null. If the case was closed after less + than half a second, the duration is rounded down to zero. + example: 120 + external_service: + type: object + properties: + connector_id: + type: string + connector_name: + type: string + external_id: + type: string + external_title: + type: string + external_url: + type: string + pushed_at: + type: string + format: date-time + pushed_by: + type: object + properties: + email: + type: string + full_name: + type: string + username: + type: string + nullable: true + example: null + id: + type: string + example: 66b9aa00-94fa-11ea-9f74-e7e108796192 + owner: + $ref: '#/components/schemas/owners' + settings: + type: object + properties: + syncAlerts: + type: boolean + example: true + severity: + $ref: '#/components/schemas/severity_property' + status: + $ref: '#/components/schemas/status' + tags: + type: array + items: + type: string + example: + - tag-1 + title: + type: string + example: Case title 1 + totalAlerts: type: integer - count_open_cases: + example: 0 + totalComment: type: integer + example: 0 + updated_at: + type: string + format: date-time + nullable: true + example: null + updated_by: + type: object + properties: + email: + type: string + full_name: + type: string + username: + type: string + nullable: true + example: null + version: + type: string + example: WzUzMiwxXQ== examples: - getStatusResponse: - $ref: '#/components/examples/get_status_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 - /s/{spaceId}/api/cases/tags: - get: - summary: Aggregates and returns a list of case tags. - description: > - You must have read privileges for the **Cases*** feature in the - **Management**, **Observability**, or **Security** section of the Kibana - feature privileges, depending on the owner of the cases you're seeking. - tags: - - cases - - kibana - parameters: - - $ref: '#/components/parameters/space_id' - - in: query - name: owner - description: >- - A filter to limit the retrieved case statistics to a specific set of - applications. If this parameter is omitted, the response contains - tags from all cases that the user has access to read. - schema: - oneOf: - - $ref: '#/components/schemas/owners' - - type: array - items: - $ref: '#/components/schemas/owners' - responses: - '200': - description: Indicates a successful call. - content: - application/json; charset=utf-8: - schema: - type: array - items: - type: string - examples: - getTagsResponse: - $ref: '#/components/examples/get_tags_response' + getCaseResponse: + $ref: '#/components/examples/get_case_response' servers: - url: https://localhost:5601 servers: @@ -5112,6 +5663,7 @@ paths: /s/{spaceId}/api/cases/{caseId}/comments: post: summary: Adds a comment or alert to a case. + operationId: addCaseComment description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -5373,6 +5925,7 @@ paths: - url: https://localhost:5601 delete: summary: Deletes all comments and alerts from a case. + operationId: deleteCaseComments description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -5391,6 +5944,7 @@ paths: - url: https://localhost:5601 patch: summary: Updates a comment or alert in a case. + operationId: updateCaseComment description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -5653,6 +6207,7 @@ paths: - url: https://localhost:5601 get: summary: Retrieves all the comments from a case. + operationId: getAllCaseComments description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -5684,6 +6239,7 @@ paths: /s/{spaceId}/api/cases/{caseId}/comments/{commentId}: delete: summary: Deletes a comment or alert from a case. + operationId: deleteCaseComment description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -5703,6 +6259,7 @@ paths: - url: https://localhost:5601 get: summary: Retrieves a comment from a case. + operationId: getCaseComment description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security*** section of the @@ -6396,6 +6953,56 @@ components: - security - tag 1 - tag 2 + get_case_response: + summary: Retrieves information about a case including its comments. + value: + id: 31cdada0-02c1-11ed-85f2-4f7c222ca2fa + version: WzM2LDFd + comments: + - id: 2134c1d0-02c2-11ed-85f2-4f7c222ca2fa + version: WzM3LDFd + type: user + owner: cases + comment: A new comment + created_at: '2022-07-13T15:40:32.335Z' + created_by: + email: null + full_name: null + username: elastic + pushed_at: null + pushed_by: null + updated_at: null + updated_by: null + totalComment: 1 + totalAlerts: 0 + title: Case title 1 + tags: + - tag 1 + settings: + syncAlerts: true + owner: cases + description: A case description + duration: null + severity: low + closed_at: null + closed_by: null + created_at: '2022-07-13T15:33:50.604Z' + created_by: + username: elastic + email: null + full_name: null + status: open + updated_at: '2022-07-13T15:40:32.335Z' + updated_by: + full_name: null + email: null + username: elastic + connector: + id: none + name: none + type: .none + fields: null + external_service: null add_comment_request: summary: Adds a comment to a case. value: diff --git a/x-pack/plugins/cases/docs/openapi/components/examples/get_case_response.yaml b/x-pack/plugins/cases/docs/openapi/components/examples/get_case_response.yaml new file mode 100644 index 0000000000000..936a21a5cfc70 --- /dev/null +++ b/x-pack/plugins/cases/docs/openapi/components/examples/get_case_response.yaml @@ -0,0 +1,44 @@ +summary: Retrieves information about a case including its comments. +value: + { + "id":"31cdada0-02c1-11ed-85f2-4f7c222ca2fa", + "version":"WzM2LDFd", + "comments":[{ + "id":"2134c1d0-02c2-11ed-85f2-4f7c222ca2fa", + "version":"WzM3LDFd", + "type":"user", + "owner":"cases", + "comment":"A new comment", + "created_at":"2022-07-13T15:40:32.335Z", + "created_by":{ + "email":null, + "full_name":null, + "username":"elastic" + }, + "pushed_at":null, + "pushed_by":null, + "updated_at":null, + "updated_by":null + }], + "totalComment":1, + "totalAlerts":0, + "title":"Case title 1", + "tags":["tag 1"], + "settings":{"syncAlerts":true}, + "owner":"cases", + "description":"A case description", + "duration":null, + "severity":"low", + "closed_at":null, + "closed_by":null, + "created_at":"2022-07-13T15:33:50.604Z", + "created_by":{"username":"elastic","email":null,"full_name":null},"status":"open", + "updated_at":"2022-07-13T15:40:32.335Z", + "updated_by":{"full_name":null,"email":null,"username":"elastic"},"connector":{ + "id":"none", + "name":"none", + "type":".none", + "fields":null + }, + "external_service":null + } \ No newline at end of file diff --git a/x-pack/plugins/cases/docs/openapi/components/examples/get_status_response.yaml b/x-pack/plugins/cases/docs/openapi/components/examples/get_status_response.yaml new file mode 100644 index 0000000000000..8a3883fe92873 --- /dev/null +++ b/x-pack/plugins/cases/docs/openapi/components/examples/get_status_response.yaml @@ -0,0 +1,7 @@ +summary: Get the number of cases in each state. +value: + { + "count_open_cases": 27, + "count_in_progress_cases": 50, + "count_closed_cases": 198 + } \ No newline at end of file diff --git a/x-pack/plugins/cases/docs/openapi/entrypoint.yaml b/x-pack/plugins/cases/docs/openapi/entrypoint.yaml index c32112eacbda0..7e05b510d5375 100644 --- a/x-pack/plugins/cases/docs/openapi/entrypoint.yaml +++ b/x-pack/plugins/cases/docs/openapi/entrypoint.yaml @@ -35,8 +35,8 @@ paths: $ref: 'paths/api@cases@status.yaml' '/api/cases/tags': $ref: 'paths/api@cases@tags.yaml' -# '/api/cases/{caseId}': -# $ref: 'paths/api@cases@{caseid}.yaml' + '/api/cases/{caseId}': + $ref: 'paths/api@cases@{caseid}.yaml' # '/api/cases/{caseId}/alerts': # $ref: 'paths/api@cases@{caseid}@alerts.yaml' '/api/cases/{caseId}/comments': @@ -66,8 +66,8 @@ paths: $ref: 'paths/s@{spaceid}@api@cases@status.yaml' '/s/{spaceId}/api/cases/tags': $ref: 'paths/s@{spaceid}@api@cases@tags.yaml' - # '/s/{spaceId}/api/cases/{caseId}': - # $ref: 'paths/s@{spaceid}@api@cases@{caseid}.yaml' + '/s/{spaceId}/api/cases/{caseId}': + $ref: 'paths/s@{spaceid}@api@cases@{caseid}.yaml' # '/s/{spaceId}/api/cases/{caseId}/alerts': # $ref: 'paths/s@{spaceid}@api@cases@{caseid}@alerts.yaml' '/s/{spaceId}/api/cases/{caseId}/comments': diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases.yaml index c12031803ca60..5375375036671 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases.yaml @@ -1,5 +1,6 @@ post: - summary: Creates a case. + summary: Creates a case in the default space. + operationId: createCaseDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -73,7 +74,8 @@ post: - url: https://localhost:5601 delete: - summary: Deletes one or more cases. + summary: Deletes one or more cases from the default space. + operationId: deleteCaseDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -97,7 +99,8 @@ delete: - url: https://localhost:5601 patch: - summary: Updates one or more cases. + summary: Updates one or more cases in the default space. + operationId: updateCaseDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@_find.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@_find.yaml index 1ef386ddd1f9d..266e00101aad5 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@_find.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@_find.yaml @@ -1,5 +1,6 @@ get: - summary: Retrieves a paginated subset of cases. + summary: Retrieves a paginated subset of cases from the default space. + operationId: getCasesDefaultSpace description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@alerts@{alertid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@alerts@{alertid}.yaml index f508f9ebc2131..e020ae577cd96 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@alerts@{alertid}.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@alerts@{alertid}.yaml @@ -1,5 +1,6 @@ get: - summary: Returns the cases associated with a specific alert. + summary: Returns the cases associated with a specific alert in the default space. + operationId: getCasesByAlertDefaultSpace description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure.yaml index 9817e37317046..527f67b3cbf22 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure.yaml @@ -1,5 +1,6 @@ get: - summary: Retrieves external connection details, such as the closure type and default connector for cases. + summary: Retrieves external connection details, such as the closure type and default connector for cases in the default space. + operationId: getCaseConfigurationDefaultSpace description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -24,7 +25,8 @@ get: - url: https://localhost:5601 post: - summary: Sets external connection details, such as the closure type and default connector for cases. + summary: Sets external connection details, such as the closure type and default connector for cases in the default space. + operationId: setCaseConfigurationDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure@connectors@_find.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure@connectors@_find.yaml index 636108e564249..8e6bddd6c681d 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure@connectors@_find.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure@connectors@_find.yaml @@ -1,5 +1,6 @@ get: - summary: Retrieves information about connectors. + summary: Retrieves information about connectors for cases in the default space. + operationId: getCaseConnectorsDefaultSpace description: > In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and Connectors** diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure@{configurationid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure@{configurationid}.yaml index e7b38f37d761f..204541dced9c1 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure@{configurationid}.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@configure@{configurationid}.yaml @@ -1,5 +1,6 @@ patch: - summary: Updates external connection details, such as the closure type and default connector for cases. + summary: Updates external connection details, such as the closure type and default connector for cases in the default space. + operationId: updateCaseConfigurationDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@reporters.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@reporters.yaml index 3f920b0414f6f..dcc601c7d4a74 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@reporters.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@reporters.yaml @@ -1,5 +1,6 @@ get: - summary: Returns information about the users who opened cases. + summary: Returns information about the users who opened cases in the default space. + operationId: getCaseReportersDefaultCase description: > You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@tags.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@tags.yaml index 68cccc0c8f723..f74dabea5bd0c 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@tags.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@tags.yaml @@ -1,5 +1,6 @@ get: - summary: Aggregates and returns a list of case tags. + summary: Aggregates and returns a list of case tags in the default space. + operationId: getCaseTagsDefaultSpace description: > You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}.yaml new file mode 100644 index 0000000000000..7290e5f5fdfba --- /dev/null +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}.yaml @@ -0,0 +1,35 @@ +get: + summary: Retrieves information about a case in the default space. + operationId: getCaseDefaultSpace + description: > + You must have `read` privileges for the **Cases** feature in the + **Management**, **Observability**, or **Security** section of the Kibana + feature privileges, depending on the owner of the case you're seeking. + tags: + - cases + - kibana + parameters: + - $ref: ../components/parameters/case_id.yaml + - in: query + name: includeComments + description: Determines whether case comments are returned. + deprecated: true + schema: + type: boolean + default: true + responses: + '200': + description: Indicates a successful call. + content: + application/json; charset=utf-8: + schema: + type: object + properties: + $ref: '../components/schemas/case_response_properties.yaml' + examples: + getCaseResponse: + $ref: '../components/examples/get_case_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}@comments.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}@comments.yaml index 15fa137fa64b4..95e49981d729d 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}@comments.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}@comments.yaml @@ -1,5 +1,6 @@ post: - summary: Adds a comment or alert to a case. + summary: Adds a comment or alert to a case in the default space. + operationId: addCaseCommentDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -36,7 +37,8 @@ post: - url: https://localhost:5601 delete: - summary: Deletes all comments and alerts from a case. + summary: Deletes all comments and alerts from a case in the default space. + operationId: deleteCaseCommentsDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -54,7 +56,8 @@ delete: - url: https://localhost:5601 patch: - summary: Updates a comment or alert in a case. + summary: Updates a comment or alert in a case in the default space. + operationId: updateCaseCommentDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -92,7 +95,8 @@ patch: - url: https://localhost:5601 get: - summary: Retrieves all the comments from a case. + summary: Retrieves all the comments from a case in the default space. + operationId: getAllCaseCommentsDefaultSpace description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, diff --git a/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}@comments@{commentid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}@comments@{commentid}.yaml index 0b167d3e8d25c..f76bd93cd8510 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}@comments@{commentid}.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/api@cases@{caseid}@comments@{commentid}.yaml @@ -1,5 +1,6 @@ delete: - summary: Deletes a comment or alert from a case. + summary: Deletes a comment or alert from a case in the default space. + operationId: deleteCaseCommentDefaultSpace description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -18,7 +19,8 @@ delete: - url: https://localhost:5601 get: - summary: Retrieves a comment from a case. + summary: Retrieves a comment from a case in the default space. + operationId: getCaseCommentDefaultSpace description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases.yaml index ebf0824e6c9a2..d0f6ddda83731 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases.yaml @@ -1,5 +1,6 @@ post: summary: Creates a case. + operationId: createCase description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -75,6 +76,7 @@ post: delete: summary: Deletes one or more cases. + operationId: deleteCase description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -100,6 +102,7 @@ delete: patch: summary: Updates one or more cases. + operationId: updateCase description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@_find.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@_find.yaml index b9652cae0b69e..48801a11dea66 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@_find.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@_find.yaml @@ -1,5 +1,6 @@ get: summary: Retrieves a paginated subset of cases. + operationId: getCases description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@alerts@{alertid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@alerts@{alertid}.yaml index 401c3a486a63b..20c365947e351 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@alerts@{alertid}.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@alerts@{alertid}.yaml @@ -1,5 +1,6 @@ get: summary: Returns the cases associated with a specific alert. + operationId: getCasesByAlert description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure.yaml index 7e52d226a8389..2df6edb39c1ce 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure.yaml @@ -1,5 +1,6 @@ get: summary: Retrieves external connection details, such as the closure type and default connector for cases. + operationId: getCaseConfiguration description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -26,6 +27,7 @@ get: post: summary: Sets external connection details, such as the closure type and default connector for cases. + operationId: setCaseConfiguration description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@connectors@_find.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@connectors@_find.yaml index 851c0e0ddda30..dfbbc498d836d 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@connectors@_find.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@connectors@_find.yaml @@ -1,5 +1,6 @@ get: - summary: Retrieves information about connectors. + summary: Retrieves information about connectors. + operationId: getCaseConnectors description: > In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and Connectors** diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@{configurationid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@{configurationid}.yaml index c5a104a987376..18336746e830b 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@{configurationid}.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@{configurationid}.yaml @@ -1,5 +1,6 @@ patch: summary: Updates external connection details, such as the closure type and default connector for cases. + operationId: updateCaseConfiguration description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@reporters.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@reporters.yaml index 186e5141dec81..52b0ec945ed1a 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@reporters.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@reporters.yaml @@ -1,5 +1,6 @@ get: summary: Returns information about the users who opened cases. + operationId: getCaseReporters description: > You must have read privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@tags.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@tags.yaml index 7798b74296126..58f1e7369d718 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@tags.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@tags.yaml @@ -1,5 +1,6 @@ get: summary: Aggregates and returns a list of case tags. + operationId: getCaseTags description: > You must have read privileges for the **Cases*** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}.yaml new file mode 100644 index 0000000000000..30c33a27a37f6 --- /dev/null +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}.yaml @@ -0,0 +1,36 @@ +get: + summary: Retrieves information about a case. + operationId: getCase + description: > + You must have `read` privileges for the **Cases** feature in the + **Management**, **Observability**, or **Security** section of the Kibana + feature privileges, depending on the owner of the case you're seeking. + tags: + - cases + - kibana + parameters: + - $ref: ../components/parameters/case_id.yaml + - $ref: '../components/parameters/space_id.yaml' + - in: query + name: includeComments + description: Determines whether case comments are returned. + deprecated: true + schema: + type: boolean + default: true + responses: + '200': + description: Indicates a successful call. + content: + application/json; charset=utf-8: + schema: + type: object + properties: + $ref: '../components/schemas/case_response_properties.yaml' + examples: + getCaseResponse: + $ref: '../components/examples/get_case_response.yaml' + servers: + - url: https://localhost:5601 +servers: + - url: https://localhost:5601 diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments.yaml index dc07c62c38c50..9d139bed703e4 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments.yaml @@ -1,5 +1,6 @@ post: summary: Adds a comment or alert to a case. + operationId: addCaseComment description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -38,6 +39,7 @@ post: delete: summary: Deletes all comments and alerts from a case. + operationId: deleteCaseComments description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -57,6 +59,7 @@ delete: patch: summary: Updates a comment or alert in a case. + operationId: updateCaseComment description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -96,6 +99,7 @@ patch: get: summary: Retrieves all the comments from a case. + operationId: getAllCaseComments description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments@{commentid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments@{commentid}.yaml index c9ad642bdd559..2ed9456aed4db 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments@{commentid}.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments@{commentid}.yaml @@ -1,5 +1,6 @@ delete: summary: Deletes a comment or alert from a case. + operationId: deleteCaseComment description: > You must have `all` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana @@ -20,6 +21,7 @@ delete: get: summary: Retrieves a comment from a case. + operationId: getCaseComment description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security*** section of the Kibana feature privileges, diff --git a/x-pack/plugins/cases/public/api/utils.test.ts b/x-pack/plugins/cases/public/api/utils.test.ts index f46ada35ffca1..e7dd99938e3cf 100644 --- a/x-pack/plugins/cases/public/api/utils.test.ts +++ b/x-pack/plugins/cases/public/api/utils.test.ts @@ -5,8 +5,29 @@ * 2.0. */ -import { allCases, allCasesSnake } from '../containers/mock'; -import { convertAllCasesToCamel, convertArrayToCamelCase, convertToCamelCase } from './utils'; +import { + allCases, + allCasesSnake, + caseWithRegisteredAttachments, + caseWithRegisteredAttachmentsSnake, + externalReferenceAttachment, + externalReferenceAttachmentSnake, + persistableStateAttachmentSnake, + persistableStateAttachment, + caseUserActionsWithRegisteredAttachments, + caseUserActionsWithRegisteredAttachmentsSnake, +} from '../containers/mock'; +import { + convertAllCasesToCamel, + convertArrayToCamelCase, + convertCaseResolveToCamelCase, + convertCasesToCamelCase, + convertCaseToCamelCase, + convertToCamelCase, + convertAttachmentsToCamelCase, + convertAttachmentToCamelCase, + convertUserActionsToCamelCase, +} from './utils'; describe('utils', () => { describe('convertArrayToCamelCase', () => { @@ -39,4 +60,64 @@ describe('utils', () => { expect(convertAllCasesToCamel(allCasesSnake)).toEqual(allCases); }); }); + + describe('convertCaseToCamelCase', () => { + it('converts a case to camel case without converting registered attachments', () => { + expect(convertCaseToCamelCase(caseWithRegisteredAttachmentsSnake)).toEqual( + caseWithRegisteredAttachments + ); + }); + }); + + describe('convertCasesToCamelCase', () => { + it('converts multiple cases to camel case without converting registered attachments', () => { + expect(convertCasesToCamelCase([caseWithRegisteredAttachmentsSnake])).toEqual([ + caseWithRegisteredAttachments, + ]); + }); + }); + + describe('convertCaseResolveToCamelCase', () => { + it('converts multiple cases to camel case without converting registered attachments', () => { + expect( + convertCaseResolveToCamelCase({ + outcome: 'aliasMatch', + case: caseWithRegisteredAttachmentsSnake, + }) + ).toEqual({ + outcome: 'aliasMatch', + case: caseWithRegisteredAttachments, + }); + }); + }); + + describe('convertAttachmentsToCamelCase', () => { + it('converts attachments camel case without converting registered attachments', () => { + expect(convertAttachmentsToCamelCase(caseWithRegisteredAttachmentsSnake.comments)).toEqual( + caseWithRegisteredAttachments.comments + ); + }); + }); + + describe('convertAttachmentToCamelCase', () => { + it('converts an external reference attachment to camel case without converting externalReferenceMetadata', () => { + expect(convertAttachmentToCamelCase(externalReferenceAttachmentSnake)).toEqual( + externalReferenceAttachment + ); + }); + + it('converts a persistable state attachment to camel case without converting externalReferenceMetadata', () => { + expect(convertAttachmentToCamelCase(persistableStateAttachmentSnake)).toEqual( + persistableStateAttachment + ); + }); + }); + + describe('convertUserActionsToCamelCase', () => { + it('converts attachments camel case without converting registered attachments', () => { + expect(convertUserActionsToCamelCase(caseUserActionsWithRegisteredAttachmentsSnake)).toEqual( + caseUserActionsWithRegisteredAttachments + ); + }); + }); }); diff --git a/x-pack/plugins/cases/public/api/utils.ts b/x-pack/plugins/cases/public/api/utils.ts index 19cb800de921b..992f078bfb7f1 100644 --- a/x-pack/plugins/cases/public/api/utils.ts +++ b/x-pack/plugins/cases/public/api/utils.ts @@ -5,9 +5,22 @@ * 2.0. */ -import { isArray, set, camelCase, isObject } from 'lodash'; -import { CasesFindResponse, CaseResponse } from '../../common/api'; -import { Cases, Case } from '../containers/types'; +import { isArray, set, camelCase, isObject, omit, get } from 'lodash'; +import { + isCommentRequestTypeExternalReference, + isCommentRequestTypePersistableState, +} from '../../common/utils/attachments'; +import { + CasesFindResponse, + CaseResponse, + CaseUserActionsResponse, + CommentRequest, + CommentResponse, + CaseResolveResponse, + CasesResponse, +} from '../../common/api'; +import { isCommentUserAction } from '../../common/utils/user_actions'; +import { Cases, Case, Comment, ResolvedCase } from '../containers/types'; export const convertArrayToCamelCase = (arrayOfSnakes: unknown[]): unknown[] => arrayOfSnakes.reduce((acc: unknown[], value) => { @@ -32,8 +45,75 @@ export const convertToCamelCase = (obj: T): U => return acc; }, {} as U); +export const convertCaseToCamelCase = (theCase: CaseResponse): Case => { + const { comments, ...restCase } = theCase; + return { + ...convertToCamelCase(restCase), + ...(comments != null ? { comments: convertAttachmentsToCamelCase(comments) } : {}), + }; +}; + +export const convertCasesToCamelCase = (cases: CasesResponse): Case[] => + cases.map(convertCaseToCamelCase); + +export const convertCaseResolveToCamelCase = (res: CaseResolveResponse): ResolvedCase => { + const { case: theCase, ...rest } = res; + return { + ...convertToCamelCase(rest), + case: convertCaseToCamelCase(theCase), + }; +}; + +export const convertAttachmentsToCamelCase = (attachments: CommentResponse[]): Comment[] => { + return attachments.map((attachment) => convertAttachmentToCamelCase(attachment)); +}; + +export const convertAttachmentToCamelCase = (attachment: CommentRequest): Comment => { + if (isCommentRequestTypeExternalReference(attachment)) { + return convertAttachmentToCamelExceptProperty(attachment, 'externalReferenceMetadata'); + } + + if (isCommentRequestTypePersistableState(attachment)) { + return convertAttachmentToCamelExceptProperty(attachment, 'persistableStateAttachmentState'); + } + + return convertToCamelCase(attachment); +}; + +export const convertUserActionsToCamelCase = (userActions: CaseUserActionsResponse) => { + return userActions.map((userAction) => { + if (isCommentUserAction(userAction)) { + const userActionWithoutPayload = omit(userAction, 'payload.comment'); + const camelCaseUserActionWithoutPayload = convertToCamelCase(userActionWithoutPayload); + + return { + ...camelCaseUserActionWithoutPayload, + payload: { + comment: convertAttachmentToCamelCase(userAction.payload.comment), + }, + }; + } + + return convertToCamelCase(userAction); + }); +}; + +const convertAttachmentToCamelExceptProperty = ( + attachment: CommentRequest, + key: string +): Comment => { + const intactValue = get(attachment, key); + const attachmentWithoutIntactValue = omit(attachment, key); + const camelCaseAttachmentWithoutIntactValue = convertToCamelCase(attachmentWithoutIntactValue); + + return { + ...camelCaseAttachmentWithoutIntactValue, + [key]: intactValue, + } as Comment; +}; + export const convertAllCasesToCamel = (snakeCases: CasesFindResponse): Cases => ({ - cases: snakeCases.cases.map((theCase) => convertToCamelCase(theCase)), + cases: convertCasesToCamelCase(snakeCases.cases), countOpenCases: snakeCases.count_open_cases, countInProgressCases: snakeCases.count_in_progress_cases, countClosedCases: snakeCases.count_closed_cases, diff --git a/x-pack/plugins/cases/public/application.tsx b/x-pack/plugins/cases/public/application.tsx index 49cdfa434923d..5acf288d3bc34 100644 --- a/x-pack/plugins/cases/public/application.tsx +++ b/x-pack/plugins/cases/public/application.tsx @@ -20,6 +20,7 @@ import { EuiThemeProvider as StyledComponentsThemeProvider } from '@kbn/kibana-r import { RenderAppProps } from './types'; import { CasesApp } from './components/app'; import { ExternalReferenceAttachmentTypeRegistry } from './client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; export const renderApp = (deps: RenderAppProps) => { const { mountParams } = deps; @@ -34,16 +35,18 @@ export const renderApp = (deps: RenderAppProps) => { interface CasesAppWithContextProps { externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry; + persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; } const CasesAppWithContext: React.FC = React.memo( - ({ externalReferenceAttachmentTypeRegistry }) => { + ({ externalReferenceAttachmentTypeRegistry, persistableStateAttachmentTypeRegistry }) => { const [darkMode] = useUiSetting$('theme:darkMode'); return ( ); @@ -73,6 +76,7 @@ export const App: React.FC<{ deps: RenderAppProps }> = ({ deps }) => { externalReferenceAttachmentTypeRegistry={ deps.externalReferenceAttachmentTypeRegistry } + persistableStateAttachmentTypeRegistry={deps.persistableStateAttachmentTypeRegistry} /> diff --git a/x-pack/plugins/cases/public/client/attachment_framework/external_reference_registry.ts b/x-pack/plugins/cases/public/client/attachment_framework/external_reference_registry.ts index a172c7ba70089..ed3eada182b0f 100644 --- a/x-pack/plugins/cases/public/client/attachment_framework/external_reference_registry.ts +++ b/x-pack/plugins/cases/public/client/attachment_framework/external_reference_registry.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { CaseRegistry } from '../../../common/registry'; +import { AttachmentTypeRegistry } from '../../../common/registry'; import { ExternalReferenceAttachmentType } from './types'; -export class ExternalReferenceAttachmentTypeRegistry extends CaseRegistry { +export class ExternalReferenceAttachmentTypeRegistry extends AttachmentTypeRegistry { constructor() { super('ExternalReferenceAttachmentTypeRegistry'); } diff --git a/x-pack/plugins/cases/public/client/attachment_framework/persistable_state_registry.ts b/x-pack/plugins/cases/public/client/attachment_framework/persistable_state_registry.ts new file mode 100644 index 0000000000000..1b8c5a1e40529 --- /dev/null +++ b/x-pack/plugins/cases/public/client/attachment_framework/persistable_state_registry.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AttachmentTypeRegistry } from '../../../common/registry'; +import { PersistableStateAttachmentType } from './types'; + +export class PersistableStateAttachmentTypeRegistry extends AttachmentTypeRegistry { + constructor() { + super('PersistableStateAttachmentTypeRegistry'); + } +} diff --git a/x-pack/plugins/cases/public/client/attachment_framework/types.ts b/x-pack/plugins/cases/public/client/attachment_framework/types.ts index 01e635c17ad59..9e62a00957aef 100644 --- a/x-pack/plugins/cases/public/client/attachment_framework/types.ts +++ b/x-pack/plugins/cases/public/client/attachment_framework/types.ts @@ -7,34 +7,49 @@ import type React from 'react'; import { EuiCommentProps, IconType } from '@elastic/eui'; -import { CommentRequestExternalReferenceType } from '../../../common/api'; +import { + CommentRequestExternalReferenceType, + CommentRequestPersistableStateType, +} from '../../../common/api'; import { Case } from '../../containers/types'; -export interface ExternalReferenceAttachmentViewObject { +export interface AttachmentViewObject { type?: EuiCommentProps['type']; timelineIcon?: EuiCommentProps['timelineIcon']; actions?: EuiCommentProps['actions']; event?: EuiCommentProps['event']; - children?: React.LazyExoticComponent; + children?: React.LazyExoticComponent>; } -export interface ExternalReferenceAttachmentViewProps { +export interface CommonAttachmentViewProps { + caseData: Pick; +} + +export interface ExternalReferenceAttachmentViewProps extends CommonAttachmentViewProps { externalReferenceId: CommentRequestExternalReferenceType['externalReferenceId']; externalReferenceMetadata: CommentRequestExternalReferenceType['externalReferenceMetadata']; - caseData: Pick; } -export interface ExternalReferenceAttachmentType { +export interface PersistableStateAttachmentViewProps extends CommonAttachmentViewProps { + persistableStateAttachmentTypeId: CommentRequestPersistableStateType['persistableStateAttachmentTypeId']; + persistableStateAttachmentState: CommentRequestPersistableStateType['persistableStateAttachmentState']; +} + +export interface AttachmentType { id: string; icon: IconType; displayName: string; - getAttachmentViewObject: ( - props: ExternalReferenceAttachmentViewProps - ) => ExternalReferenceAttachmentViewObject; + getAttachmentViewObject: () => AttachmentViewObject; } +export type ExternalReferenceAttachmentType = AttachmentType; +export type PersistableStateAttachmentType = AttachmentType; + export interface AttachmentFramework { registerExternalReference: ( externalReferenceAttachmentType: ExternalReferenceAttachmentType ) => void; + registerPersistableState: ( + persistableStateAttachmentType: PersistableStateAttachmentType + ) => void; } diff --git a/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx b/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx index 37145c59b94ad..93c107f8cc726 100644 --- a/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx +++ b/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx @@ -13,7 +13,7 @@ import { CasesProvider, CasesContextProps } from '../../components/cases_context type GetAllCasesSelectorModalPropsInternal = AllCasesSelectorModalProps & CasesContextProps; export type GetAllCasesSelectorModalProps = Omit< GetAllCasesSelectorModalPropsInternal, - 'externalReferenceAttachmentTypeRegistry' + 'externalReferenceAttachmentTypeRegistry' | 'persistableStateAttachmentTypeRegistry' >; const AllCasesSelectorModalLazy: React.FC = lazy( @@ -21,13 +21,21 @@ const AllCasesSelectorModalLazy: React.FC = lazy( ); export const getAllCasesSelectorModalLazy = ({ externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, owner, permissions, hiddenStatuses, onRowClick, onClose, }: GetAllCasesSelectorModalPropsInternal) => ( - + }> ; +export type GetCasesProps = Omit< + GetCasesPropsInternal, + 'externalReferenceAttachmentTypeRegistry' | 'persistableStateAttachmentTypeRegistry' +>; const CasesRoutesLazy: React.FC = lazy(() => import('../../components/app/routes')); export const getCasesLazy = ({ externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, owner, permissions, basePath, @@ -33,6 +37,7 @@ export const getCasesLazy = ({ ; const CasesProviderLazy: React.FC<{ value: GetCasesContextPropsInternal }> = lazy( @@ -21,6 +21,7 @@ const CasesProviderLazy: React.FC<{ value: GetCasesContextPropsInternal }> = laz const CasesProviderLazyWrapper = ({ externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, owner, permissions, features, @@ -32,6 +33,7 @@ const CasesProviderLazyWrapper = ({ ): (() => React.FC) => { const CasesProviderLazyWrapperWithRegistry: React.FC = ({ children, @@ -59,6 +62,7 @@ export const getCasesContextLazy = ({ {children} diff --git a/x-pack/plugins/cases/public/client/ui/get_create_case_flyout.tsx b/x-pack/plugins/cases/public/client/ui/get_create_case_flyout.tsx index 5149b71d19dd4..e6f6b5465173e 100644 --- a/x-pack/plugins/cases/public/client/ui/get_create_case_flyout.tsx +++ b/x-pack/plugins/cases/public/client/ui/get_create_case_flyout.tsx @@ -13,7 +13,7 @@ import { CasesProvider, CasesContextProps } from '../../components/cases_context type GetCreateCaseFlyoutPropsInternal = CreateCaseFlyoutProps & CasesContextProps; export type GetCreateCaseFlyoutProps = Omit< GetCreateCaseFlyoutPropsInternal, - 'externalReferenceAttachmentTypeRegistry' + 'externalReferenceAttachmentTypeRegistry' | 'persistableStateAttachmentTypeRegistry' >; export const CreateCaseFlyoutLazy: React.FC = lazy( @@ -21,6 +21,7 @@ export const CreateCaseFlyoutLazy: React.FC = lazy( ); export const getCreateCaseFlyoutLazy = ({ externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, owner, permissions, features, @@ -29,7 +30,15 @@ export const getCreateCaseFlyoutLazy = ({ onSuccess, attachments, }: GetCreateCaseFlyoutPropsInternal) => ( - + }> ; const RecentCasesLazy: React.FC = lazy( @@ -21,11 +21,19 @@ const RecentCasesLazy: React.FC = lazy( ); export const getRecentCasesLazy = ({ externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, owner, permissions, maxCasesToShow, }: GetRecentCasesPropsInternal) => ( - + }> diff --git a/x-pack/plugins/cases/public/common/mock/test_providers.tsx b/x-pack/plugins/cases/public/common/mock/test_providers.tsx index 4d1bd4b68accd..84bf68f7fa814 100644 --- a/x-pack/plugins/cases/public/common/mock/test_providers.tsx +++ b/x-pack/plugins/cases/public/common/mock/test_providers.tsx @@ -25,6 +25,7 @@ import { StartServices } from '../../types'; import { ReleasePhase } from '../../components/types'; import { CasesPermissions } from '../../client/helpers/capabilities'; import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; interface TestProviderProps { children: React.ReactNode; @@ -33,6 +34,7 @@ interface TestProviderProps { owner?: string[]; releasePhase?: ReleasePhase; externalReferenceAttachmentTypeRegistry?: ExternalReferenceAttachmentTypeRegistry; + persistableStateAttachmentTypeRegistry?: PersistableStateAttachmentTypeRegistry; } type UiRender = (ui: React.ReactElement, options?: RenderOptions) => RenderResult; @@ -47,6 +49,7 @@ const TestProvidersComponent: React.FC = ({ permissions = allCasesPermissions(), releasePhase = 'ga', externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(), + persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(), }) => { const queryClient = new QueryClient({ defaultOptions: { @@ -62,7 +65,13 @@ const TestProvidersComponent: React.FC = ({ ({ eui: euiDarkVars, darkMode: true })}> {children} @@ -78,6 +87,7 @@ export const TestProviders = React.memo(TestProvidersComponent); export interface AppMockRenderer { externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry; + persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; render: UiRender; coreStart: StartServices; queryClient: QueryClient; @@ -111,6 +121,7 @@ export const createAppMockRenderer = ({ permissions = allCasesPermissions(), releasePhase = 'ga', externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(), + persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(), }: Omit = {}): AppMockRenderer => { const services = createStartServicesMock(); const queryClient = new QueryClient({ @@ -129,6 +140,7 @@ export const createAppMockRenderer = ({ { const useCreateAttachmentsMock = useCreateAttachments as jest.Mock; const externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(); +const persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(); describe('use cases add to existing case modal hook', () => { useCreateAttachmentsMock.mockReturnValue({ @@ -60,6 +62,7 @@ describe('use cases add to existing case modal hook', () => { = ({ externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, }) => { const userCapabilities = useApplicationCapabilities(); @@ -29,6 +32,7 @@ const CasesAppComponent: React.FC = ({ {getCasesLazy({ externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, owner: [APP_OWNER], useFetchAlertData: () => [false, {}], permissions: userCapabilities.generalCases, diff --git a/x-pack/plugins/cases/public/components/cases_context/index.tsx b/x-pack/plugins/cases/public/components/cases_context/index.tsx index de63eefb79cc5..161fcce7abcfb 100644 --- a/x-pack/plugins/cases/public/components/cases_context/index.tsx +++ b/x-pack/plugins/cases/public/components/cases_context/index.tsx @@ -20,11 +20,13 @@ import { CasesFeaturesAllRequired, CasesFeatures } from '../../containers/types' import { CasesGlobalComponents } from './cases_global_components'; import { ReleasePhase } from '../types'; import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; export type CasesContextValueDispatch = Dispatch; export interface CasesContextValue { externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry; + persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; owner: string[]; appId: string; appTitle: string; @@ -41,7 +43,10 @@ export interface CasesContextValue { export interface CasesContextProps extends Pick< CasesContextValue, - 'owner' | 'permissions' | 'externalReferenceAttachmentTypeRegistry' + | 'owner' + | 'permissions' + | 'externalReferenceAttachmentTypeRegistry' + | 'persistableStateAttachmentTypeRegistry' > { basePath?: string; features?: CasesFeatures; @@ -59,6 +64,7 @@ export const CasesProvider: React.FC<{ value: CasesContextProps }> = ({ children, value: { externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, owner, permissions, basePath = DEFAULT_BASE_PATH, @@ -70,6 +76,7 @@ export const CasesProvider: React.FC<{ value: CasesContextProps }> = ({ const [state, dispatch] = useReducer(casesContextReducer, getInitialCasesContextState()); const [value, setValue] = useState(() => ({ externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, owner, permissions, basePath, diff --git a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx index d553295eaef98..b49349f9844fa 100644 --- a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx +++ b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.test.tsx @@ -15,10 +15,12 @@ import { CasesContextStoreActionsList } from '../../cases_context/cases_context_ import { useCasesAddToNewCaseFlyout } from './use_cases_add_to_new_case_flyout'; import { allCasesPermissions } from '../../../common/mock'; import { ExternalReferenceAttachmentTypeRegistry } from '../../../client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from '../../../client/attachment_framework/persistable_state_registry'; jest.mock('../../../common/use_cases_toast'); const externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(); +const persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(); describe('use cases add to new case flyout hook', () => { const dispatch = jest.fn(); @@ -30,6 +32,7 @@ describe('use cases add to new case flyout hook', () => { diff --git a/x-pack/plugins/cases/public/components/header_page/__snapshots__/index.test.tsx.snap b/x-pack/plugins/cases/public/components/header_page/__snapshots__/index.test.tsx.snap index 75f368a9cc61a..cfb75e0c286f2 100644 --- a/x-pack/plugins/cases/public/components/header_page/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/cases/public/components/header_page/__snapshots__/index.test.tsx.snap @@ -46,6 +46,10 @@ exports[`HeaderPage it renders 1`] = ` "all": true, "read": true, }, + "persistableStateAttachmentTypeRegistry": PersistableStateAttachmentTypeRegistry { + "collection": Map {}, + "name": "PersistableStateAttachmentTypeRegistry", + }, } } > diff --git a/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx b/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx index d25f3b997aeda..82ed36ef25243 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx @@ -63,7 +63,7 @@ describe('RecentCases', () => { ); - expect(getAllByTestId('case-details-link')).toHaveLength(7); + expect(getAllByTestId('case-details-link')).toHaveLength(8); }); it('render max cases correctly', () => { diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx index d7f4c9ee0150b..3c41caecdb0aa 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx @@ -18,14 +18,18 @@ import { getExternalReferenceAttachment, getExternalReferenceUserAction, getHostIsolationUserAction, + getPersistableStateAttachment, + getPersistableStateUserAction, getUserAction, hostIsolationComment, + persistableStateAttachment, } from '../../../containers/mock'; import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../../common/mock'; import { createCommentUserActionBuilder } from './comment'; import { getMockBuilderArgs } from '../mock'; import { useCaseViewParams } from '../../../common/navigation'; import { ExternalReferenceAttachmentTypeRegistry } from '../../../client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from '../../../client/attachment_framework/persistable_state_registry'; jest.mock('../../../common/lib/kibana'); jest.mock('../../../common/navigation/hooks'); @@ -204,7 +208,7 @@ describe('createCommentUserActionBuilder', () => { const createdUserAction = builder.build(); const result = appMockRender.render(); - expect(result.getByTestId('comment-external-reference-.test')).toBeInTheDocument(); + expect(result.getByTestId('comment-externalReference-.test')).toBeInTheDocument(); expect(result.getByTestId('copy-link-external-reference-comment-id')).toBeInTheDocument(); expect(result.getByTestId('user-action-username-with-avatar')).toBeInTheDocument(); expect(screen.getByText('added a chart')).toBeInTheDocument(); @@ -227,7 +231,7 @@ describe('createCommentUserActionBuilder', () => { const createdUserAction = builder.build(); const result = appMockRender.render(); - expect(result.getByTestId('comment-external-reference-not-found')).toBeInTheDocument(); + expect(result.getByTestId('comment-externalReference-not-found')).toBeInTheDocument(); expect(screen.getByText('added an attachment of type')).toBeInTheDocument(); expect(screen.getByText('Attachment type is not registered')).toBeInTheDocument(); }); @@ -259,7 +263,94 @@ describe('createCommentUserActionBuilder', () => { const createdUserAction = builder.build(); const result = appMockRender.render(); - expect(result.getByTestId('comment-external-reference-.test')).toBeInTheDocument(); + expect(result.getByTestId('comment-externalReference-.test')).toBeInTheDocument(); + expect(screen.getByText('Attachment actions')).toBeInTheDocument(); + }); + }); + + describe('Persistable state', () => { + let appMockRender: AppMockRenderer; + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + }); + + it('renders correctly a persistable state attachment', async () => { + const persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(); + persistableStateAttachmentTypeRegistry.register( + getPersistableStateAttachment({ type: 'regular' }) + ); + + const userAction = getPersistableStateUserAction(); + const builder = createCommentUserActionBuilder({ + ...builderArgs, + persistableStateAttachmentTypeRegistry, + caseData: { + ...builderArgs.caseData, + comments: [persistableStateAttachment], + }, + userAction, + }); + + const createdUserAction = builder.build(); + const result = appMockRender.render(); + + expect(result.getByTestId('comment-persistableState-.test')).toBeInTheDocument(); + expect(result.getByTestId('copy-link-persistable-state-comment-id')).toBeInTheDocument(); + expect(result.getByTestId('user-action-username-with-avatar')).toBeInTheDocument(); + expect(screen.getByText('added an embeddable')).toBeInTheDocument(); + }); + + it('renders correctly if the reference is not registered', async () => { + const persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(); + + const userAction = getPersistableStateUserAction(); + const builder = createCommentUserActionBuilder({ + ...builderArgs, + persistableStateAttachmentTypeRegistry, + caseData: { + ...builderArgs.caseData, + comments: [persistableStateAttachment], + }, + userAction, + }); + + const createdUserAction = builder.build(); + const result = appMockRender.render(); + + expect(result.getByTestId('comment-persistableState-not-found')).toBeInTheDocument(); + expect(screen.getByText('added an attachment of type')).toBeInTheDocument(); + expect(screen.getByText('Attachment type is not registered')).toBeInTheDocument(); + }); + + it('renders correctly a persistable state with actions', async () => { + const ActionsView = () => { + return <>{'Attachment actions'}; + }; + + const attachment = getPersistableStateAttachment({ + type: 'regular', + actions: , + }); + + const persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(); + persistableStateAttachmentTypeRegistry.register(attachment); + + const userAction = getPersistableStateUserAction(); + const builder = createCommentUserActionBuilder({ + ...builderArgs, + persistableStateAttachmentTypeRegistry, + caseData: { + ...builderArgs.caseData, + comments: [persistableStateAttachment], + }, + userAction, + }); + + const createdUserAction = builder.build(); + const result = appMockRender.render(); + + expect(result.getByTestId('comment-persistableState-.test')).toBeInTheDocument(); expect(screen.getByText('Attachment actions')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx index 0dfd5876cea6b..ef5b4418d454f 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx @@ -16,6 +16,7 @@ import { createUserAttachmentUserActionBuilder } from './user'; import { createAlertAttachmentUserActionBuilder } from './alert'; import { createActionAttachmentUserActionBuilder } from './actions'; import { createExternalReferenceAttachmentUserActionBuilder } from './external_reference'; +import { createPersistableStateAttachmentUserActionBuilder } from './persistable_state'; const getUpdateLabelTitle = () => `${i18n.EDITED_FIELD} ${i18n.COMMENT.toLowerCase()}`; const getDeleteLabelTitle = () => `${i18n.REMOVED_FIELD} ${i18n.COMMENT.toLowerCase()}`; @@ -41,6 +42,7 @@ const getCreateCommentUserAction = ({ userAction, caseData, externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, comment, commentRefs, manageMarkdownEditIds, @@ -89,14 +91,18 @@ const getCreateCommentUserAction = ({ onRuleDetailsClick, onShowAlertDetails, }); + return alertBuilder.build(); + case CommentType.actions: const actionBuilder = createActionAttachmentUserActionBuilder({ userAction, comment, actionsNavigation, }); + return actionBuilder.build(); + case CommentType.externalReference: const externalReferenceBuilder = createExternalReferenceAttachmentUserActionBuilder({ userAction, @@ -104,7 +110,18 @@ const getCreateCommentUserAction = ({ externalReferenceAttachmentTypeRegistry, caseData, }); + return externalReferenceBuilder.build(); + + case CommentType.persistableState: + const persistableBuilder = createPersistableStateAttachmentUserActionBuilder({ + userAction, + comment, + persistableStateAttachmentTypeRegistry, + caseData, + }); + + return persistableBuilder.build(); default: return []; } @@ -113,6 +130,7 @@ const getCreateCommentUserAction = ({ export const createCommentUserActionBuilder: UserActionBuilder = ({ caseData, externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, userAction, commentRefs, manageMarkdownEditIds, @@ -148,6 +166,7 @@ export const createCommentUserActionBuilder: UserActionBuilder = ({ caseData, userAction: commentUserAction, externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, comment, commentRefs, manageMarkdownEditIds, diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx index 3a28e8abd65d3..10b676be711b7 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx @@ -5,16 +5,10 @@ * 2.0. */ -import React, { Suspense } from 'react'; - -import { EuiCallOut, EuiCode, EuiLoadingSpinner } from '@elastic/eui'; import { CommentResponseExternalReferenceType } from '../../../../common/api'; import { UserActionBuilder, UserActionBuilderArgs } from '../types'; -import { UserActionTimestamp } from '../timestamp'; import { SnakeToCamelCase } from '../../../../common/types'; -import { UserActionUsernameWithAvatar } from '../avatar_username'; -import { UserActionCopyLink } from '../copy_link'; -import { ATTACHMENT_NOT_REGISTERED_ERROR, DEFAULT_EVENT_ATTACHMENT_TITLE } from './translations'; +import { createRegisteredAttachmentUserActionBuilder } from './registered_attachments'; type BuilderArgs = Pick< UserActionBuilderArgs, @@ -28,75 +22,16 @@ export const createExternalReferenceAttachmentUserActionBuilder = ({ comment, externalReferenceAttachmentTypeRegistry, caseData, -}: BuilderArgs): ReturnType => ({ - // TODO: Fix this manually. Issue #123375 - // eslint-disable-next-line react/display-name - build: () => { - const isTypeRegistered = externalReferenceAttachmentTypeRegistry.has( - comment.externalReferenceAttachmentTypeId - ); - - if (!isTypeRegistered) { - return [ - { - username: ( - - ), - event: ( - <> - {`${DEFAULT_EVENT_ATTACHMENT_TITLE} `} - {comment.externalReferenceAttachmentTypeId} - - ), - className: 'comment-external-reference-not-found', - 'data-test-subj': 'comment-external-reference-not-found', - timestamp: , - children: ( - - ), - }, - ]; - } - - const externalReferenceType = externalReferenceAttachmentTypeRegistry.get( - comment.externalReferenceAttachmentTypeId - ); - - const externalReferenceViewObject = externalReferenceType.getAttachmentViewObject({ +}: BuilderArgs): ReturnType => { + return createRegisteredAttachmentUserActionBuilder({ + userAction, + comment, + registry: externalReferenceAttachmentTypeRegistry, + caseData, + getId: () => comment.externalReferenceAttachmentTypeId, + getAttachmentViewProps: () => ({ externalReferenceId: comment.externalReferenceId, externalReferenceMetadata: comment.externalReferenceMetadata, - caseData: { id: caseData.id, title: caseData.title }, - }); - - return [ - { - username: ( - - ), - type: externalReferenceViewObject.type, - className: `comment-external-reference${comment.externalReferenceAttachmentTypeId}`, - event: externalReferenceViewObject.event, - 'data-test-subj': `comment-external-reference-${comment.externalReferenceAttachmentTypeId}`, - timestamp: , - timelineIcon: externalReferenceViewObject.timelineIcon, - actions: ( - <> - - {externalReferenceViewObject.actions} - - ), - children: externalReferenceViewObject.children ? ( - }> - {React.createElement(externalReferenceViewObject.children)} - - ) : undefined, - }, - ]; - }, -}); + }), + }); +}; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx new file mode 100644 index 0000000000000..80e4d0d3743ce --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CommentResponseTypePersistableState } from '../../../../common/api'; +import { UserActionBuilder, UserActionBuilderArgs } from '../types'; +import { SnakeToCamelCase } from '../../../../common/types'; +import { createRegisteredAttachmentUserActionBuilder } from './registered_attachments'; + +type BuilderArgs = Pick< + UserActionBuilderArgs, + 'userAction' | 'persistableStateAttachmentTypeRegistry' | 'caseData' +> & { + comment: SnakeToCamelCase; +}; + +export const createPersistableStateAttachmentUserActionBuilder = ({ + userAction, + comment, + persistableStateAttachmentTypeRegistry, + caseData, +}: BuilderArgs): ReturnType => { + return createRegisteredAttachmentUserActionBuilder({ + userAction, + comment, + registry: persistableStateAttachmentTypeRegistry, + caseData, + getId: () => comment.persistableStateAttachmentTypeId, + getAttachmentViewProps: () => ({ + persistableStateAttachmentTypeId: comment.persistableStateAttachmentTypeId, + persistableStateAttachmentState: comment.persistableStateAttachmentState, + }), + }); +}; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx new file mode 100644 index 0000000000000..6a05f3c64a491 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx @@ -0,0 +1,113 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { Suspense } from 'react'; + +import { EuiCallOut, EuiCode, EuiLoadingSpinner } from '@elastic/eui'; +import { AttachmentType } from '../../../client/attachment_framework/types'; +import { AttachmentTypeRegistry } from '../../../../common/registry'; +import { CommentResponse } from '../../../../common/api'; +import { UserActionBuilder, UserActionBuilderArgs } from '../types'; +import { UserActionTimestamp } from '../timestamp'; +import { SnakeToCamelCase } from '../../../../common/types'; +import { UserActionUsernameWithAvatar } from '../avatar_username'; +import { UserActionCopyLink } from '../copy_link'; +import { ATTACHMENT_NOT_REGISTERED_ERROR, DEFAULT_EVENT_ATTACHMENT_TITLE } from './translations'; + +type BuilderArgs = Pick & { + comment: SnakeToCamelCase; + registry: R; + getId: () => string; + getAttachmentViewProps: () => object; +}; + +export const createRegisteredAttachmentUserActionBuilder = < + C extends CommentResponse, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + R extends AttachmentTypeRegistry> +>({ + userAction, + comment, + registry, + caseData, + getId, + getAttachmentViewProps, +}: BuilderArgs): ReturnType => ({ + // TODO: Fix this manually. Issue #123375 + // eslint-disable-next-line react/display-name + build: () => { + const attachmentTypeId: string = getId(); + const isTypeRegistered = registry.has(attachmentTypeId); + + if (!isTypeRegistered) { + return [ + { + username: ( + + ), + event: ( + <> + {`${DEFAULT_EVENT_ATTACHMENT_TITLE} `} + {attachmentTypeId} + + ), + className: `comment-${comment.type}-not-found`, + 'data-test-subj': `comment-${comment.type}-not-found`, + timestamp: , + children: ( + + ), + }, + ]; + } + + const attachmentType = registry.get(attachmentTypeId); + + const attachmentViewObject = attachmentType.getAttachmentViewObject(); + const props = { + ...getAttachmentViewProps(), + caseData: { id: caseData.id, title: caseData.title }, + }; + + return [ + { + username: ( + + ), + type: attachmentViewObject.type, + className: `comment-${comment.type}-attachment-${attachmentTypeId}`, + event: attachmentViewObject.event, + 'data-test-subj': `comment-${comment.type}-${attachmentTypeId}`, + timestamp: , + timelineIcon: attachmentViewObject.timelineIcon, + actions: ( + <> + + {attachmentViewObject.actions} + + ), + children: attachmentViewObject.children ? ( + }> + {React.createElement(attachmentViewObject.children, props)} + + ) : undefined, + }, + ]; + }, +}); diff --git a/x-pack/plugins/cases/public/components/user_actions/index.tsx b/x-pack/plugins/cases/public/components/user_actions/index.tsx index 1c456f90a71e7..7224eee213719 100644 --- a/x-pack/plugins/cases/public/components/user_actions/index.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/index.tsx @@ -95,7 +95,8 @@ export const UserActions = React.memo( const { detailName: caseId, commentId } = useCaseViewParams(); const [initLoading, setInitLoading] = useState(true); const currentUser = useCurrentUser(); - const { externalReferenceAttachmentTypeRegistry } = useCasesContext(); + const { externalReferenceAttachmentTypeRegistry, persistableStateAttachmentTypeRegistry } = + useCasesContext(); const alertIdsWithoutRuleInfo = useMemo( () => getManualAlertIdsWithNoRuleId(caseData.comments), @@ -180,6 +181,7 @@ export const UserActions = React.memo( const userActionBuilder = builder({ caseData, externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, userAction, caseServices, comments: caseData.comments, @@ -207,6 +209,7 @@ export const UserActions = React.memo( [ caseUserActions, externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, descriptionCommentListObj, caseData, caseServices, diff --git a/x-pack/plugins/cases/public/components/user_actions/mock.ts b/x-pack/plugins/cases/public/components/user_actions/mock.ts index 777241aca71eb..b3a7909b06929 100644 --- a/x-pack/plugins/cases/public/components/user_actions/mock.ts +++ b/x-pack/plugins/cases/public/components/user_actions/mock.ts @@ -8,6 +8,7 @@ import { Actions } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; import { basicCase, basicPush, getUserAction } from '../../containers/mock'; import { UserActionBuilderArgs } from './types'; @@ -58,10 +59,12 @@ export const getMockBuilderArgs = (): UserActionBuilderArgs => { const handleManageQuote = jest.fn(); const handleOutlineComment = jest.fn(); const externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(); + const persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(); return { userAction, externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, caseData: basicCase, comments: basicCase.comments, caseServices, diff --git a/x-pack/plugins/cases/public/components/user_actions/types.ts b/x-pack/plugins/cases/public/components/user_actions/types.ts index a834328075a09..8ba409468851e 100644 --- a/x-pack/plugins/cases/public/components/user_actions/types.ts +++ b/x-pack/plugins/cases/public/components/user_actions/types.ts @@ -16,6 +16,7 @@ import { CasesNavigation } from '../links'; import { UNSUPPORTED_ACTION_TYPES } from './constants'; import type { OnUpdateFields } from '../case_view/types'; import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; export interface UserActionTreeProps { caseServices: CaseServices; @@ -38,6 +39,7 @@ export type SupportedUserActionTypes = keyof Omit { +describe('Cases API', () => { describe('deleteCases', () => { beforeEach(() => { fetchMock.mockClear(); @@ -128,6 +133,12 @@ describe('Case Configuration API', () => { const resp = await getCase(data, true, abortCtrl.signal); expect(resp).toEqual(basicCase); }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue(caseWithRegisteredAttachmentsSnake); + const resp = await getCase(data, true, abortCtrl.signal); + expect(resp).toEqual(caseWithRegisteredAttachments); + }); }); describe('resolveCase', () => { @@ -156,6 +167,21 @@ describe('Case Configuration API', () => { const resp = await resolveCase(caseId, true, abortCtrl.signal); expect(resp).toEqual({ ...basicResolveCase, case: basicCase, targetAliasId }); }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue({ + ...basicResolveCase, + case: caseWithRegisteredAttachmentsSnake, + target_alias_id: targetAliasId, + }); + + const resp = await resolveCase(caseId, true, abortCtrl.signal); + expect(resp).toEqual({ + ...basicResolveCase, + case: caseWithRegisteredAttachments, + targetAliasId, + }); + }); }); describe('getCases', () => { @@ -278,7 +304,7 @@ describe('Case Configuration API', () => { }); }); - test('should return correct response', async () => { + test('should return correct response and not covert to camel case registered attachments', async () => { fetchMock.mockResolvedValue(allCasesSnake); const resp = await getCases({ filterOptions: { ...DEFAULT_FILTER_OPTIONS, owner: [SECURITY_SOLUTION_OWNER] }, @@ -339,6 +365,12 @@ describe('Case Configuration API', () => { const resp = await getCaseUserActions(basicCase.id, abortCtrl.signal); expect(resp).toEqual(caseUserActions); }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue(caseUserActionsWithRegisteredAttachmentsSnake); + const resp = await getCaseUserActions(basicCase.id, abortCtrl.signal); + expect(resp).toEqual(caseUserActionsWithRegisteredAttachments); + }); }); describe('getReporters', () => { @@ -392,9 +424,12 @@ describe('Case Configuration API', () => { fetchMock.mockClear(); fetchMock.mockResolvedValue([basicCaseSnake]); }); + const data = { description: 'updated description' }; + test('should be called with correct check url, method, signal', async () => { await patchCase(basicCase.id, data, basicCase.version, abortCtrl.signal); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}`, { method: 'PATCH', body: JSON.stringify({ @@ -411,7 +446,20 @@ describe('Case Configuration API', () => { basicCase.version, abortCtrl.signal ); - expect(resp).toEqual({ ...[basicCase] }); + + expect(resp).toEqual([basicCase]); + }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue([caseWithRegisteredAttachmentsSnake]); + const resp = await patchCase( + basicCase.id, + { description: 'updated description' }, + basicCase.version, + abortCtrl.signal + ); + + expect(resp).toEqual([caseWithRegisteredAttachments]); }); }); @@ -420,6 +468,7 @@ describe('Case Configuration API', () => { fetchMock.mockClear(); fetchMock.mockResolvedValue(casesSnake); }); + const data = [ { status: CaseStatuses.closed, @@ -437,9 +486,9 @@ describe('Case Configuration API', () => { }); }); - test('should return correct response', async () => { + test('should return correct response should not covert to camel case registered attachments', async () => { const resp = await patchCasesStatus(data, abortCtrl.signal); - expect(resp).toEqual({ ...cases }); + expect(resp).toEqual(cases); }); }); @@ -458,6 +507,7 @@ describe('Case Configuration API', () => { signal: abortCtrl.signal, owner: SECURITY_SOLUTION_OWNER, }); + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/comments`, { method: 'PATCH', body: JSON.stringify({ @@ -482,6 +532,21 @@ describe('Case Configuration API', () => { }); expect(resp).toEqual(basicCase); }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue(caseWithRegisteredAttachmentsSnake); + + const resp = await patchComment({ + caseId: basicCase.id, + commentId: basicCase.comments[0].id, + commentUpdate: 'updated comment', + version: basicCase.comments[0].version, + signal: abortCtrl.signal, + owner: SECURITY_SOLUTION_OWNER, + }); + + expect(resp).toEqual(caseWithRegisteredAttachments); + }); }); describe('postCase', () => { @@ -518,6 +583,12 @@ describe('Case Configuration API', () => { const resp = await postCase(data, abortCtrl.signal); expect(resp).toEqual(basicCase); }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue(caseWithRegisteredAttachmentsSnake); + const resp = await postCase(data, abortCtrl.signal); + expect(resp).toEqual(caseWithRegisteredAttachments); + }); }); describe('createAttachments', () => { @@ -559,6 +630,12 @@ describe('Case Configuration API', () => { const resp = await createAttachments(data, basicCase.id, abortCtrl.signal); expect(resp).toEqual(basicCase); }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue(caseWithRegisteredAttachmentsSnake); + const resp = await createAttachments(data, basicCase.id, abortCtrl.signal); + expect(resp).toEqual(caseWithRegisteredAttachments); + }); }); describe('pushCase', () => { @@ -585,6 +662,12 @@ describe('Case Configuration API', () => { const resp = await pushCase(basicCase.id, connectorId, abortCtrl.signal); expect(resp).toEqual(pushedCase); }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue(caseWithRegisteredAttachmentsSnake); + const resp = await pushCase(basicCase.id, connectorId, abortCtrl.signal); + expect(resp).toEqual(caseWithRegisteredAttachments); + }); }); describe('deleteComment', () => { @@ -628,4 +711,38 @@ describe('Case Configuration API', () => { expect(resp).toEqual(['siem', 'observability']); }); }); + + describe('postComment', () => { + beforeEach(() => { + fetchMock.mockClear(); + fetchMock.mockResolvedValue(basicCaseSnake); + }); + + const data = { + comment: 'Solve this fast!', + type: CommentType.user as const, + owner: SECURITY_SOLUTION_OWNER, + }; + + test('should be called with correct check url, method, signal', async () => { + await postComment(data, basicCase.id, abortCtrl.signal); + + expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/${basicCase.id}/comments`, { + method: 'POST', + body: JSON.stringify(data), + signal: abortCtrl.signal, + }); + }); + + test('should return correct response', async () => { + const resp = await postComment(data, basicCase.id, abortCtrl.signal); + expect(resp).toEqual(basicCase); + }); + + test('should not covert to camel case registered attachments', async () => { + fetchMock.mockResolvedValue(caseWithRegisteredAttachmentsSnake); + const resp = await postComment(data, basicCase.id, abortCtrl.signal); + expect(resp).toEqual(caseWithRegisteredAttachments); + }); + }); }); diff --git a/x-pack/plugins/cases/public/containers/api.ts b/x-pack/plugins/cases/public/containers/api.ts index 344f390908104..f01ac793f66c9 100644 --- a/x-pack/plugins/cases/public/containers/api.ts +++ b/x-pack/plugins/cases/public/containers/api.ts @@ -45,7 +45,15 @@ import { getAllConnectorTypesUrl } from '../../common/utils/connectors_api'; import { KibanaServices } from '../common/lib/kibana'; -import { convertAllCasesToCamel, convertToCamelCase, convertArrayToCamelCase } from '../api/utils'; +import { + convertAllCasesToCamel, + convertToCamelCase, + convertArrayToCamelCase, + convertUserActionsToCamelCase, + convertCaseToCamelCase, + convertCasesToCamelCase, + convertCaseResolveToCamelCase, +} from '../api/utils'; import { ActionLicense, @@ -77,7 +85,7 @@ export const getCase = async ( }, signal, }); - return convertToCamelCase(decodeCaseResponse(response)); + return convertCaseToCamelCase(decodeCaseResponse(response)); }; export const resolveCase = async ( @@ -95,7 +103,7 @@ export const resolveCase = async ( signal, } ); - return convertToCamelCase(decodeCaseResolveResponse(response)); + return convertCaseResolveToCamelCase(decodeCaseResolveResponse(response)); }; export const getTags = async (signal: AbortSignal, owner: string[]): Promise => { @@ -145,7 +153,10 @@ export const getCaseUserActions = async ( signal, } ); - return convertArrayToCamelCase(decodeCaseUserActionsResponse(response)) as CaseUserActions[]; + + return convertUserActionsToCamelCase( + decodeCaseUserActionsResponse(response) + ) as CaseUserActions[]; }; export const getCases = async ({ @@ -190,7 +201,7 @@ export const postCase = async (newCase: CasePostRequest, signal: AbortSignal): P body: JSON.stringify(newCase), signal, }); - return convertToCamelCase(decodeCaseResponse(response)); + return convertCaseToCamelCase(decodeCaseResponse(response)); }; export const patchCase = async ( @@ -207,7 +218,7 @@ export const patchCase = async ( body: JSON.stringify({ cases: [{ ...updatedCase, id: caseId, version }] }), signal, }); - return convertToCamelCase(decodeCasesResponse(response)); + return convertCasesToCamelCase(decodeCasesResponse(response)); }; export const patchCasesStatus = async ( @@ -219,7 +230,8 @@ export const patchCasesStatus = async ( body: JSON.stringify({ cases }), signal, }); - return convertToCamelCase(decodeCasesResponse(response)); + + return convertCasesToCamelCase(decodeCasesResponse(response)); }; export const postComment = async ( @@ -235,7 +247,7 @@ export const postComment = async ( signal, } ); - return convertToCamelCase(decodeCaseResponse(response)); + return convertCaseToCamelCase(decodeCaseResponse(response)); }; export const patchComment = async ({ @@ -264,7 +276,7 @@ export const patchComment = async ({ }), signal, }); - return convertToCamelCase(decodeCaseResponse(response)); + return convertCaseToCamelCase(decodeCaseResponse(response)); }; export const deleteComment = async ({ @@ -305,7 +317,7 @@ export const pushCase = async ( } ); - return convertToCamelCase(decodeCaseResponse(response)); + return convertCaseToCamelCase(decodeCaseResponse(response)); }; export const getActionLicense = async (signal: AbortSignal): Promise => { @@ -333,7 +345,7 @@ export const createAttachments = async ( signal, } ); - return convertToCamelCase(decodeCaseResponse(response)); + return convertCaseToCamelCase(decodeCaseResponse(response)); }; export const getFeatureIds = async ( diff --git a/x-pack/plugins/cases/public/containers/mock.ts b/x-pack/plugins/cases/public/containers/mock.ts index e691558ad690b..b09420c59800f 100644 --- a/x-pack/plugins/cases/public/containers/mock.ts +++ b/x-pack/plugins/cases/public/containers/mock.ts @@ -14,6 +14,7 @@ import type { AlertComment, CasesMetrics, ExternalReferenceComment, + PersistableComment, } from '../../common/ui/types'; import { Actions, @@ -41,7 +42,8 @@ import { SnakeToCamelCase } from '../../common/types'; import { covertToSnakeCase } from './utils'; import { ExternalReferenceAttachmentType, - ExternalReferenceAttachmentViewObject, + AttachmentViewObject, + PersistableStateAttachmentType, } from '../client/attachment_framework/types'; export { connectorsMock } from '../common/mock/connectors'; @@ -171,7 +173,22 @@ export const externalReferenceAttachment: ExternalReferenceComment = { externalReferenceId: 'my-id', externalReferenceStorage: { type: ExternalReferenceStorageType.elasticSearchDoc }, externalReferenceAttachmentTypeId: '.test', - externalReferenceMetadata: null, + externalReferenceMetadata: { test_foo: 'foo' }, + createdAt: basicCreatedAt, + createdBy: elasticUser, + owner: SECURITY_SOLUTION_OWNER, + pushedAt: null, + pushedBy: null, + updatedAt: null, + updatedBy: null, + version: 'WzQ3LDFc', +}; + +export const persistableStateAttachment: PersistableComment = { + type: CommentType.persistableState, + id: 'persistable-state-comment-id', + persistableStateAttachmentState: { test_foo: 'foo' }, + persistableStateAttachmentTypeId: '.test', createdAt: basicCreatedAt, createdBy: elasticUser, owner: SECURITY_SOLUTION_OWNER, @@ -218,6 +235,7 @@ export const caseWithAlerts = { totalAlerts: 2, id: caseWithAlertsId, }; + export const caseWithAlertsSyncOff = { ...basicCase, totalAlerts: 2, @@ -227,6 +245,12 @@ export const caseWithAlertsSyncOff = { id: caseWithAlertsSyncOffId, }; +export const caseWithRegisteredAttachments = { + ...basicCase, + id: 'case-with-registered-attachment', + comments: [externalReferenceAttachment, persistableStateAttachment], +}; + export const basicResolvedCase: ResolvedCase = { case: basicCase, outcome: 'aliasMatch', @@ -377,6 +401,7 @@ export const cases: Case[] = [ { ...basicCase, id: '4', totalComment: 0, comments: [] }, caseWithAlerts, caseWithAlertsSyncOff, + caseWithRegisteredAttachments, ]; export const allCases: Cases = { @@ -425,6 +450,38 @@ export const basicCommentSnake: CommentResponse = { version: 'WzQ3LDFc', }; +export const externalReferenceAttachmentSnake: CommentResponse = { + type: CommentType.externalReference, + id: 'external-reference-comment-id', + externalReferenceId: 'my-id', + externalReferenceMetadata: { test_foo: 'foo' }, + externalReferenceAttachmentTypeId: '.test', + externalReferenceStorage: { type: ExternalReferenceStorageType.elasticSearchDoc }, + created_at: basicCreatedAt, + created_by: elasticUserSnake, + owner: SECURITY_SOLUTION_OWNER, + pushed_at: null, + pushed_by: null, + updated_at: null, + updated_by: null, + version: 'WzQ3LDFc', +}; + +export const persistableStateAttachmentSnake: CommentResponse = { + type: CommentType.persistableState, + id: 'persistable-state-comment-id', + persistableStateAttachmentState: { test_foo: 'foo' }, + persistableStateAttachmentTypeId: '.test', + created_at: basicCreatedAt, + created_by: elasticUserSnake, + owner: SECURITY_SOLUTION_OWNER, + pushed_at: null, + pushed_by: null, + updated_at: null, + updated_by: null, + version: 'WzQ3LDFc', +}; + export const basicCaseSnake: CaseResponse = { ...basicCase, status: CaseStatuses.open, @@ -446,6 +503,7 @@ export const caseWithAlertsSnake = { totalAlerts: 2, id: caseWithAlertsId, }; + export const caseWithAlertsSyncOffSnake = { ...basicCaseSnake, totalAlerts: 2, @@ -455,6 +513,12 @@ export const caseWithAlertsSyncOffSnake = { id: caseWithAlertsSyncOffId, }; +export const caseWithRegisteredAttachmentsSnake = { + ...basicCaseSnake, + id: 'case-with-registered-attachment', + comments: [externalReferenceAttachmentSnake, persistableStateAttachmentSnake], +}; + export const casesStatusSnake: CasesStatusResponse = { count_closed_cases: 130, count_in_progress_cases: 40, @@ -502,6 +566,7 @@ export const casesSnake: CasesResponse = [ { ...basicCaseSnake, id: '4', totalComment: 0, comments: [] }, caseWithAlertsSnake, caseWithAlertsSyncOffSnake, + caseWithRegisteredAttachmentsSnake, ]; export const allCasesSnake: CasesFindResponse = { @@ -645,6 +710,32 @@ export const caseUserActionsSnake: CaseUserActionsResponse = [ getUserActionSnake('description', Actions.update), ]; +export const caseUserActionsWithRegisteredAttachmentsSnake: CaseUserActionsResponse = [ + getUserActionSnake('description', Actions.create), + { + created_at: basicCreatedAt, + created_by: elasticUserSnake, + case_id: 'case-with-registered-attachment', + comment_id: null, + owner: SECURITY_SOLUTION_OWNER, + type: 'comment', + action: 'create', + action_id: 'create-comment-id', + payload: { comment: externalReferenceAttachmentSnake }, + }, + { + created_at: basicCreatedAt, + created_by: elasticUserSnake, + case_id: 'case-with-registered-attachment', + comment_id: null, + owner: SECURITY_SOLUTION_OWNER, + type: 'comment', + action: 'create', + action_id: 'create-comment-id', + payload: { comment: persistableStateAttachmentSnake }, + }, +]; + export const getJiraConnector = (overrides?: Partial): CaseConnector => { return { id: '123', @@ -701,6 +792,32 @@ export const caseUserActions: CaseUserActions[] = [ getUserAction('description', Actions.update), ]; +export const caseUserActionsWithRegisteredAttachments: CaseUserActions[] = [ + getUserAction('description', Actions.create), + { + createdAt: basicCreatedAt, + createdBy: elasticUser, + caseId: 'case-with-registered-attachment', + commentId: null, + owner: SECURITY_SOLUTION_OWNER, + type: 'comment', + action: 'create', + actionId: 'create-comment-id', + payload: { comment: externalReferenceAttachment }, + }, + { + createdAt: basicCreatedAt, + createdBy: elasticUser, + caseId: 'case-with-registered-attachment', + commentId: null, + owner: SECURITY_SOLUTION_OWNER, + type: 'comment', + action: 'create', + actionId: 'create-comment-id', + payload: { comment: persistableStateAttachment }, + }, +]; + // components tests export const useGetCasesMockState = { data: allCases, @@ -735,7 +852,7 @@ export const getExternalReferenceUserAction = (): SnakeToCamelCase< }); export const getExternalReferenceAttachment = ( - viewObject: ExternalReferenceAttachmentViewObject = {} + viewObject: AttachmentViewObject = {} ): ExternalReferenceAttachmentType => ({ id: '.test', icon: 'casesApp', @@ -747,3 +864,34 @@ export const getExternalReferenceAttachment = ( ...viewObject, }), }); + +export const getPersistableStateUserAction = (): SnakeToCamelCase< + UserActionWithResponse +> => ({ + ...getUserAction(ActionTypes.comment, Actions.create), + actionId: 'persistable-state-action-id', + type: ActionTypes.comment, + commentId: 'persistable-state-comment-id', + payload: { + comment: { + type: CommentType.persistableState, + persistableStateAttachmentState: { test_foo: 'foo' }, + persistableStateAttachmentTypeId: '.test', + owner: SECURITY_SOLUTION_OWNER, + }, + }, +}); + +export const getPersistableStateAttachment = ( + viewObject: AttachmentViewObject = {} +): PersistableStateAttachmentType => ({ + id: '.test', + icon: 'casesApp', + displayName: 'Test', + getAttachmentViewObject: () => ({ + type: 'update', + event: 'added an embeddable', + timelineIcon: 'casesApp', + ...viewObject, + }), +}); diff --git a/x-pack/plugins/cases/public/plugin.ts b/x-pack/plugins/cases/public/plugin.ts index 1be8a1e428f9c..410ce5b31b07f 100644 --- a/x-pack/plugins/cases/public/plugin.ts +++ b/x-pack/plugins/cases/public/plugin.ts @@ -25,6 +25,7 @@ import { getCreateCaseFlyoutLazy } from './client/ui/get_create_case_flyout'; import { getRecentCasesLazy } from './client/ui/get_recent_cases'; import { groupAlertsByRule } from './client/helpers/group_alerts_by_rule'; import { ExternalReferenceAttachmentTypeRegistry } from './client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; /** * @public @@ -36,16 +37,19 @@ export class CasesUiPlugin private readonly kibanaVersion: string; private readonly storage = new Storage(localStorage); private externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry; + private persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; constructor(private readonly initializerContext: PluginInitializerContext) { this.kibanaVersion = initializerContext.env.packageInfo.version; this.externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(); + this.persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(); } public setup(core: CoreSetup, plugins: CasesPluginSetup): CasesUiSetup { const kibanaVersion = this.kibanaVersion; const storage = this.storage; const externalReferenceAttachmentTypeRegistry = this.externalReferenceAttachmentTypeRegistry; + const persistableStateAttachmentTypeRegistry = this.persistableStateAttachmentTypeRegistry; if (plugins.home) { plugins.home.featureCatalogue.register({ @@ -79,6 +83,7 @@ export class CasesUiPlugin storage, kibanaVersion, externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry, }); }, }); @@ -88,6 +93,9 @@ export class CasesUiPlugin registerExternalReference: (externalReferenceAttachmentType) => { this.externalReferenceAttachmentTypeRegistry.register(externalReferenceAttachmentType); }, + registerPersistableState: (persistableStateAttachmentType) => { + this.persistableStateAttachmentTypeRegistry.register(persistableStateAttachmentType); + }, }, }; } @@ -102,6 +110,7 @@ export class CasesUiPlugin */ const getCasesContext = getCasesContextLazy({ externalReferenceAttachmentTypeRegistry: this.externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry: this.persistableStateAttachmentTypeRegistry, }); return { @@ -111,24 +120,28 @@ export class CasesUiPlugin getCasesLazy({ ...props, externalReferenceAttachmentTypeRegistry: this.externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry: this.persistableStateAttachmentTypeRegistry, }), getCasesContext, getRecentCases: (props) => getRecentCasesLazy({ ...props, externalReferenceAttachmentTypeRegistry: this.externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry: this.persistableStateAttachmentTypeRegistry, }), // @deprecated Please use the hook getUseCasesAddToNewCaseFlyout getCreateCaseFlyout: (props) => getCreateCaseFlyoutLazy({ ...props, externalReferenceAttachmentTypeRegistry: this.externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry: this.persistableStateAttachmentTypeRegistry, }), // @deprecated Please use the hook getUseCasesAddToExistingCaseModal getAllCasesSelectorModal: (props) => getAllCasesSelectorModalLazy({ ...props, externalReferenceAttachmentTypeRegistry: this.externalReferenceAttachmentTypeRegistry, + persistableStateAttachmentTypeRegistry: this.persistableStateAttachmentTypeRegistry, }), }, hooks: { diff --git a/x-pack/plugins/cases/public/types.ts b/x-pack/plugins/cases/public/types.ts index 9836210292b43..b417fd0202516 100644 --- a/x-pack/plugins/cases/public/types.ts +++ b/x-pack/plugins/cases/public/types.ts @@ -40,6 +40,7 @@ import type { Cases, CasesStatus, CasesMetrics } from '../common/ui'; import { groupAlertsByRule } from './client/helpers/group_alerts_by_rule'; import type { AttachmentFramework } from './client/attachment_framework/types'; import { ExternalReferenceAttachmentTypeRegistry } from './client/attachment_framework/external_reference_registry'; +import { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; export interface CasesPluginSetup { security: SecurityPluginSetup; @@ -75,6 +76,7 @@ export interface RenderAppProps { storage: Storage; kibanaVersion: string; externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry; + persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; } export interface CasesUiSetup { diff --git a/x-pack/plugins/cases/server/attachment_framework/persistable_state_registry.ts b/x-pack/plugins/cases/server/attachment_framework/persistable_state_registry.ts index b36e75245ac47..5ca965a7da726 100644 --- a/x-pack/plugins/cases/server/attachment_framework/persistable_state_registry.ts +++ b/x-pack/plugins/cases/server/attachment_framework/persistable_state_registry.ts @@ -6,10 +6,10 @@ */ import { identity } from 'lodash'; -import { CaseRegistry } from '../../common/registry'; +import { AttachmentTypeRegistry } from '../../common/registry'; import { PersistableStateAttachmentType, PersistableStateAttachmentTypeSetup } from './types'; -export class PersistableStateAttachmentTypeRegistry extends CaseRegistry { +export class PersistableStateAttachmentTypeRegistry extends AttachmentTypeRegistry { constructor() { super('PersistableStateAttachmentTypeRegistry'); } diff --git a/x-pack/plugins/cases/server/attachment_framework/so_references.ts b/x-pack/plugins/cases/server/attachment_framework/so_references.ts index 4e18d128586fa..f6f2435235289 100644 --- a/x-pack/plugins/cases/server/attachment_framework/so_references.ts +++ b/x-pack/plugins/cases/server/attachment_framework/so_references.ts @@ -6,8 +6,8 @@ */ import { SavedObjectReference } from '@kbn/core/types'; +import { isCommentRequestTypePersistableState } from '../../common/utils/attachments'; import { CommentRequest, CommentRequestPersistableStateType } from '../../common/api'; -import { isCommentRequestTypePersistableState } from '../common/utils'; import { PersistableStateAttachmentTypeRegistry } from './persistable_state_registry'; interface SavedObjectAttributesAndReferences { diff --git a/x-pack/plugins/cases/server/client/attachments/update.ts b/x-pack/plugins/cases/server/client/attachments/update.ts index f003f988d98d8..fefc9d61e7c89 100644 --- a/x-pack/plugins/cases/server/client/attachments/update.ts +++ b/x-pack/plugins/cases/server/client/attachments/update.ts @@ -9,9 +9,9 @@ import Boom from '@hapi/boom'; import { CaseCommentModel } from '../../common/models'; import { createCaseError } from '../../common/error'; +import { isCommentRequestTypeExternalReference } from '../../../common/utils/attachments'; import { CaseResponse, CommentPatchRequest } from '../../../common/api'; import { CASE_SAVED_OBJECT } from '../../../common/constants'; -import { isCommentRequestTypeExternalReference } from '../../common/utils'; import { CasesClientArgs } from '..'; import { decodeCommentRequest } from '../utils'; import { Operations } from '../../authorization'; diff --git a/x-pack/plugins/cases/server/client/utils.ts b/x-pack/plugins/cases/server/client/utils.ts index 2c0137ba13d3e..1e25bd3476621 100644 --- a/x-pack/plugins/cases/server/client/utils.ts +++ b/x-pack/plugins/cases/server/client/utils.ts @@ -13,6 +13,10 @@ import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import { nodeBuilder, fromKueryExpression, KueryNode, escapeKuery } from '@kbn/es-query'; +import { + isCommentRequestTypeExternalReference, + isCommentRequestTypePersistableState, +} from '../../common/utils/attachments'; import { CASE_SAVED_OBJECT } from '../../common/constants'; import { OWNER_FIELD, @@ -36,9 +40,7 @@ import { isCommentRequestTypeAlert, isCommentRequestTypeUser, isCommentRequestTypeActions, - isCommentRequestTypeExternalReference, assertUnreachable, - isCommentRequestTypePersistableState, } from '../common/utils'; import { SavedObjectFindOptionsKueryNode } from '../common/types'; diff --git a/x-pack/plugins/cases/server/common/utils.ts b/x-pack/plugins/cases/server/common/utils.ts index bd22c600fe817..19c840a25d048 100644 --- a/x-pack/plugins/cases/server/common/utils.ts +++ b/x-pack/plugins/cases/server/common/utils.ts @@ -27,8 +27,6 @@ import { CommentRequestActionsType, CommentRequestAlertType, CommentRequestExternalReferenceSOType, - CommentRequestExternalReferenceType, - CommentRequestPersistableStateType, CommentRequestUserType, CommentResponse, CommentsResponse, @@ -237,15 +235,6 @@ export const isCommentRequestTypeAlert = ( return context.type === CommentType.alert; }; -/** - * A type narrowing function for external reference attachments. - */ -export const isCommentRequestTypeExternalReference = ( - context: CommentRequest -): context is CommentRequestExternalReferenceType => { - return context.type === CommentType.externalReference; -}; - /** * A type narrowing function for external reference so attachments. */ @@ -258,15 +247,6 @@ export const isCommentRequestTypeExternalReferenceSO = ( ); }; -/** - * A type narrowing function for persistable state attachments. - */ -export const isCommentRequestTypePersistableState = ( - context: Partial -): context is CommentRequestPersistableStateType => { - return context.type === CommentType.persistableState; -}; - /** * Adds the ids and indices to a map of statuses */ diff --git a/x-pack/plugins/cases/server/services/user_actions/index.ts b/x-pack/plugins/cases/server/services/user_actions/index.ts index 38855146e70de..3adde90f369d1 100644 --- a/x-pack/plugins/cases/server/services/user_actions/index.ts +++ b/x-pack/plugins/cases/server/services/user_actions/index.ts @@ -18,6 +18,7 @@ import { import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { KueryNode } from '@kbn/es-query'; +import { isCommentRequestTypePersistableState } from '../../../common/utils/attachments'; import { isConnectorUserAction, isPushedUserAction, @@ -54,11 +55,7 @@ import { findConnectorIdReference } from '../transform'; import { buildFilter, combineFilters, isTwoArraysDifference } from '../../client/utils'; import { BuilderParameters, BuilderReturnValue, CommonArguments, CreateUserAction } from './types'; import { BuilderFactory } from './builder_factory'; -import { - defaultSortField, - isCommentRequestTypeExternalReferenceSO, - isCommentRequestTypePersistableState, -} from '../../common/utils'; +import { defaultSortField, isCommentRequestTypeExternalReferenceSO } from '../../common/utils'; import { PersistableStateAttachmentTypeRegistry } from '../../attachment_framework/persistable_state_registry'; import { injectPersistableReferencesToSO } from '../../attachment_framework/so_references'; diff --git a/x-pack/plugins/cloud_security_posture/kibana.json b/x-pack/plugins/cloud_security_posture/kibana.json index 123e1e6ccf0e8..a5fa332e4d5b4 100755 --- a/x-pack/plugins/cloud_security_posture/kibana.json +++ b/x-pack/plugins/cloud_security_posture/kibana.json @@ -10,6 +10,6 @@ "description": "The cloud security posture plugin", "server": true, "ui": true, - "requiredPlugins": ["navigation", "data", "fleet", "unifiedSearch", "taskManager", "security", "charts"], + "requiredPlugins": ["navigation", "data", "fleet", "unifiedSearch", "taskManager", "security", "charts", "discover"], "requiredBundles": ["kibanaReact"] } diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx new file mode 100644 index 0000000000000..3ca9e9cf2d02c --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.test.tsx @@ -0,0 +1,276 @@ +/* + * Copyright 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 Chance from 'chance'; +import { useCisKubernetesIntegration } from '../common/api/use_cis_kubernetes_integration'; +import { + DEFAULT_NO_DATA_TEST_SUBJECT, + ERROR_STATE_TEST_SUBJECT, + isCommonError, + LOADING_STATE_TEST_SUBJECT, + PACKAGE_NOT_INSTALLED_TEST_SUBJECT, +} from './cloud_posture_page'; +import { createReactQueryResponse } from '../test/fixtures/react_query'; +import { TestProvider } from '../test/test_provider'; +import { coreMock } from '@kbn/core/public/mocks'; +import { render, screen } from '@testing-library/react'; +import React, { ComponentProps } from 'react'; +import { UseQueryResult } from 'react-query'; +import { CloudPosturePage } from './cloud_posture_page'; +import { NoDataPage } from '@kbn/kibana-react-plugin/public'; + +const chance = new Chance(); +jest.mock('../common/api/use_cis_kubernetes_integration'); + +describe('', () => { + beforeEach(() => { + jest.resetAllMocks(); + // if package installation status is 'not_installed', CloudPosturePage will render a noDataConfig prompt + (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: { item: { status: 'installed' } }, + })); + }); + + const renderCloudPosturePage = ( + props: ComponentProps = { children: null } + ) => { + const mockCore = coreMock.createStart(); + + render( + + + + ); + }; + + it('renders children if integration is installed', () => { + const children = chance.sentence(); + renderCloudPosturePage({ children }); + + expect(screen.getByText(children)).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders integrations installation prompt if integration is not installed', () => { + (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + isLoading: false, + data: { item: { status: 'not_installed' } }, + })); + + const children = chance.sentence(); + renderCloudPosturePage({ children }); + + expect(screen.getByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default loading state when the integration query is loading', () => { + (useCisKubernetesIntegration as jest.Mock).mockImplementation( + () => + createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult + ); + + const children = chance.sentence(); + renderCloudPosturePage({ children }); + + expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default error state when the integration query has an error', () => { + (useCisKubernetesIntegration as jest.Mock).mockImplementation( + () => + createReactQueryResponse({ + status: 'error', + error: new Error('error'), + }) as unknown as UseQueryResult + ); + + const children = chance.sentence(); + renderCloudPosturePage({ children }); + + expect(screen.getByTestId(ERROR_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default loading text when query isLoading', () => { + const query = createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudPosturePage({ children, query }); + + expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default loading text when query is idle', () => { + const query = createReactQueryResponse({ + status: 'idle', + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudPosturePage({ children, query }); + + expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default error texts when query isError', () => { + const error = chance.sentence(); + const message = chance.sentence(); + const statusCode = chance.integer(); + + const query = createReactQueryResponse({ + status: 'error', + error: { + body: { + error, + message, + statusCode, + }, + }, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudPosturePage({ children, query }); + + [error, message, statusCode].forEach((text) => + expect(screen.getByText(text, { exact: false })).toBeInTheDocument() + ); + expect(screen.getByTestId(ERROR_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('prefers custom error render', () => { + const error = chance.sentence(); + const message = chance.sentence(); + const statusCode = chance.integer(); + + const query = createReactQueryResponse({ + status: 'error', + error: { + body: { + error, + message, + statusCode, + }, + }, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudPosturePage({ + children, + query, + errorRender: (err) =>
{isCommonError(err) && err.body.message}
, + }); + + expect(screen.getByText(message)).toBeInTheDocument(); + [error, statusCode].forEach((text) => expect(screen.queryByText(text)).not.toBeInTheDocument()); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('prefers custom loading render', () => { + const loading = chance.sentence(); + + const query = createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudPosturePage({ + children, + query, + loadingRender: () =>
{loading}
, + }); + + expect(screen.getByText(loading)).toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders no data prompt when query data is undefined', () => { + const query = createReactQueryResponse({ + status: 'success', + data: undefined, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudPosturePage({ children, query }); + + expect(screen.getByTestId(DEFAULT_NO_DATA_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('prefers custom no data prompt', () => { + const pageTitle = chance.sentence(); + const solution = chance.sentence(); + const docsLink = chance.sentence(); + const noDataRenderer = () => ( + + ); + + const query = createReactQueryResponse({ + status: 'success', + data: undefined, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudPosturePage({ + children, + query, + noDataRenderer, + }); + + expect(screen.getByText(pageTitle)).toBeInTheDocument(); + expect(screen.getAllByText(solution, { exact: false })[0]).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx new file mode 100644 index 0000000000000..e56795d3b1380 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_posture_page.tsx @@ -0,0 +1,193 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import type { UseQueryResult } from 'react-query'; +import { EuiEmptyPrompt } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { NoDataPage } from '@kbn/kibana-react-plugin/public'; +import { css } from '@emotion/react'; +import { CspLoadingState } from './csp_loading_state'; +import { useCisKubernetesIntegration } from '../common/api/use_cis_kubernetes_integration'; +import { useCISIntegrationLink } from '../common/navigation/use_navigate_to_cis_integration'; + +export const LOADING_STATE_TEST_SUBJECT = 'cloud_posture_page_loading'; +export const ERROR_STATE_TEST_SUBJECT = 'cloud_posture_page_error'; +export const PACKAGE_NOT_INSTALLED_TEST_SUBJECT = 'cloud_posture_page_package_not_installed'; +export const DEFAULT_NO_DATA_TEST_SUBJECT = 'cloud_posture_page_no_data'; + +interface CommonError { + body: { + error: string; + message: string; + statusCode: number; + }; +} + +export const isCommonError = (error: unknown): error is CommonError => { + if ( + !(error as any)?.body || + !(error as any)?.body?.error || + !(error as any)?.body?.message || + !(error as any)?.body?.statusCode + ) { + return false; + } + + return true; +}; + +const packageNotInstalledRenderer = (cisIntegrationLink?: string) => ( + +); + +const defaultLoadingRenderer = () => ( + + + +); + +const defaultErrorRenderer = (error: unknown) => ( + + + + } + body={ + isCommonError(error) ? ( +

+ +

+ ) : undefined + } + /> +); + +const defaultNoDataRenderer = () => { + return ( + + ); +}; + +interface CloudPosturePageProps { + children: React.ReactNode; + query?: UseQueryResult; + loadingRender?: () => React.ReactNode; + errorRender?: (error: TError) => React.ReactNode; + noDataRenderer?: () => React.ReactNode; +} + +export const CloudPosturePage = ({ + children, + query, + loadingRender = defaultLoadingRenderer, + errorRender = defaultErrorRenderer, + noDataRenderer = defaultNoDataRenderer, +}: CloudPosturePageProps) => { + const cisKubernetesPackageInfo = useCisKubernetesIntegration(); + const cisIntegrationLink = useCISIntegrationLink(); + + const render = () => { + if (cisKubernetesPackageInfo.isError) { + return defaultErrorRenderer(cisKubernetesPackageInfo.error); + } + + if (cisKubernetesPackageInfo.isLoading || cisKubernetesPackageInfo.isIdle) { + return defaultLoadingRenderer(); + } + + if (cisKubernetesPackageInfo.data.item.status !== 'installed') { + return packageNotInstalledRenderer(cisIntegrationLink); + } + + if (!query) { + return children; + } + + if (query.isError) { + return errorRender(query.error); + } + + if (query.isLoading || query.isIdle) { + return loadingRender(); + } + + if (!query.data) { + return noDataRenderer(); + } + + return children; + }; + + return <>{render()}; +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/csp_loading_state.tsx b/x-pack/plugins/cloud_security_posture/public/components/csp_loading_state.tsx index 21a01c9f52ace..7b2e9f0f03ae7 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/csp_loading_state.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/csp_loading_state.tsx @@ -18,6 +18,7 @@ export const CspLoadingState: React.FunctionComponent<{ ['data-test-subj']?: str { it('maps navigation items to side navigation items', () => { const navigationItem = createNavigationItemFixture(); @@ -52,230 +31,3 @@ describe('getSideNavItems', () => { expect(sideNavItems).toHaveLength(0); }); }); - -describe('', () => { - beforeEach(() => { - jest.resetAllMocks(); - // if package installation status is 'not_installed', CspPageTemplate will render a noDataConfig prompt - (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ - isSuccess: true, - isLoading: false, - data: { item: { status: 'installed' } }, - })); - }); - - const renderCspPageTemplate = (props: ComponentProps = {}) => { - const mockCore = coreMock.createStart(); - - render( - - - - ); - }; - - it('renders children if integration is installed', () => { - const children = chance.sentence(); - renderCspPageTemplate({ children }); - - expect(screen.getByText(children)).toBeInTheDocument(); - expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - packageNotInstalledUniqueTexts.forEach((text) => - expect(screen.queryByText(text)).not.toBeInTheDocument() - ); - }); - - it('renders integrations installation prompt if integration is not installed', () => { - (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ - isSuccess: true, - isLoading: false, - data: { item: { status: 'not_installed' } }, - })); - - const children = chance.sentence(); - renderCspPageTemplate({ children }); - - Object.values(PACKAGE_NOT_INSTALLED_TEXT).forEach((text) => - expect(screen.getAllByText(text)[0]).toBeInTheDocument() - ); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - }); - - it('renders default loading text when query isLoading', () => { - const query = createReactQueryResponse({ - status: 'loading', - }) as unknown as UseQueryResult; - - const children = chance.sentence(); - renderCspPageTemplate({ children, query }); - - expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - packageNotInstalledUniqueTexts.forEach((text) => - expect(screen.queryByText(text)).not.toBeInTheDocument() - ); - }); - - it('renders default loading text when query is idle', () => { - const query = createReactQueryResponse({ - status: 'idle', - }) as unknown as UseQueryResult; - - const children = chance.sentence(); - renderCspPageTemplate({ children, query }); - - expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - packageNotInstalledUniqueTexts.forEach((text) => - expect(screen.queryByText(text)).not.toBeInTheDocument() - ); - }); - - it('renders default error texts when query isError', () => { - const error = chance.sentence(); - const message = chance.sentence(); - const statusCode = chance.integer(); - - const query = createReactQueryResponse({ - status: 'error', - error: { - body: { - error, - message, - statusCode, - }, - }, - }) as unknown as UseQueryResult; - - const children = chance.sentence(); - renderCspPageTemplate({ children, query }); - - [error, message, statusCode].forEach((text) => - expect(screen.getByText(text, { exact: false })).toBeInTheDocument() - ); - expect(screen.getByTestId(ERROR_STATE_TEST_SUBJECT)).toBeInTheDocument(); - expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - packageNotInstalledUniqueTexts.forEach((text) => - expect(screen.queryByText(text)).not.toBeInTheDocument() - ); - }); - - it('prefers custom error render', () => { - const error = chance.sentence(); - const message = chance.sentence(); - const statusCode = chance.integer(); - - const query = createReactQueryResponse({ - status: 'error', - error: { - body: { - error, - message, - statusCode, - }, - }, - }) as unknown as UseQueryResult; - - const children = chance.sentence(); - renderCspPageTemplate({ - children, - query, - errorRender: (err) =>
{isCommonError(err) && err.body.message}
, - }); - - expect(screen.getByText(message)).toBeInTheDocument(); - [error, statusCode].forEach((text) => expect(screen.queryByText(text)).not.toBeInTheDocument()); - expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - packageNotInstalledUniqueTexts.forEach((text) => - expect(screen.queryByText(text)).not.toBeInTheDocument() - ); - }); - - it('prefers custom loading render', () => { - const loading = chance.sentence(); - - const query = createReactQueryResponse({ - status: 'loading', - }) as unknown as UseQueryResult; - - const children = chance.sentence(); - renderCspPageTemplate({ - children, - query, - loadingRender: () =>
{loading}
, - }); - - expect(screen.getByText(loading)).toBeInTheDocument(); - expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - packageNotInstalledUniqueTexts.forEach((text) => - expect(screen.queryByText(text)).not.toBeInTheDocument() - ); - }); - - it('renders noDataConfig prompt when query data is undefined', () => { - const query = createReactQueryResponse({ - status: 'success', - data: undefined, - }) as unknown as UseQueryResult; - - const children = chance.sentence(); - renderCspPageTemplate({ children, query }); - - expect(screen.getByText(DEFAULT_NO_DATA_TEXT.PAGE_TITLE)).toBeInTheDocument(); - expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - packageNotInstalledUniqueTexts.forEach((text) => - expect(screen.queryByText(text)).not.toBeInTheDocument() - ); - }); - - it('prefers custom noDataConfig prompt', () => { - const pageTitle = chance.sentence(); - const solution = chance.sentence(); - const docsLink = chance.sentence(); - - const query = createReactQueryResponse({ - status: 'success', - data: undefined, - }) as unknown as UseQueryResult; - - const children = chance.sentence(); - renderCspPageTemplate({ - children, - query, - noDataConfig: { pageTitle, solution, docsLink, actions: {} }, - }); - - expect(screen.getByText(pageTitle)).toBeInTheDocument(); - expect(screen.getAllByText(solution, { exact: false })[0]).toBeInTheDocument(); - expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); - packageNotInstalledUniqueTexts.forEach((text) => - expect(screen.queryByText(text)).not.toBeInTheDocument() - ); - }); -}); diff --git a/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx b/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx index 24ac368b0ec01..7a6d4272edbc3 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx @@ -5,45 +5,18 @@ * 2.0. */ import React from 'react'; -import type { UseQueryResult } from 'react-query'; import { NavLink } from 'react-router-dom'; -import { EuiEmptyPrompt, EuiErrorBoundary, EuiTitle } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { KibanaPageTemplate, type KibanaPageTemplateProps } from '@kbn/kibana-react-plugin/public'; +import { i18n } from '@kbn/i18n'; +import { EuiErrorBoundary } from '@elastic/eui'; +import { KibanaPageTemplate, type KibanaPageTemplateProps } from '@kbn/shared-ux-components'; import { allNavigationItems } from '../common/navigation/constants'; import type { CspNavigationItem } from '../common/navigation/types'; -import { CspLoadingState } from './csp_loading_state'; -import { - CLOUD_SECURITY_POSTURE, - DEFAULT_NO_DATA_TEXT, - PACKAGE_NOT_INSTALLED_TEXT, -} from './translations'; -import { useCisKubernetesIntegration } from '../common/api/use_cis_kubernetes_integration'; -import { useCISIntegrationLink } from '../common/navigation/use_navigate_to_cis_integration'; - -export interface CommonError { - body: { - error: string; - message: string; - statusCode: number; - }; -} - -export const isCommonError = (x: any): x is CommonError => { - if (!('body' in x)) return false; - - const { - body: { error, message, statusCode }, - } = x; - - return !!(error && message && statusCode); -}; const activeItemStyle = { fontWeight: 700 }; export const getSideNavItems = ( navigationItems: Record -): NonNullable['items'] => +): NonNullable['items']> => Object.entries(navigationItems) .filter(([_, navigationItem]) => !navigationItem.disabled) .map(([id, navigationItem]) => ({ @@ -58,7 +31,9 @@ export const getSideNavItems = ( const DEFAULT_PAGE_PROPS: KibanaPageTemplateProps = { solutionNav: { - name: CLOUD_SECURITY_POSTURE, + name: i18n.translate('xpack.csp.cspPageTemplate.navigationTitle', { + defaultMessage: 'Cloud Security Posture', + }), items: getSideNavItems({ dashboard: allNavigationItems.dashboard, findings: allNavigationItems.findings, @@ -68,146 +43,13 @@ const DEFAULT_PAGE_PROPS: KibanaPageTemplateProps = { restrictWidth: false, }; -export const DEFAULT_NO_DATA_CONFIG: KibanaPageTemplateProps['noDataConfig'] = { - pageTitle: DEFAULT_NO_DATA_TEXT.PAGE_TITLE, - solution: DEFAULT_NO_DATA_TEXT.SOLUTION, - // TODO: Add real docs link once we have it - docsLink: 'https://www.elastic.co/guide/index.html', - logo: 'logoSecurity', - actions: {}, -}; - -export const LOADING_STATE_TEST_SUBJECT = 'csp_page_template_loading'; -export const ERROR_STATE_TEST_SUBJECT = 'csp_page_template_error'; - -const getPackageNotInstalledNoDataConfig = ( - cisIntegrationLink?: string -): KibanaPageTemplateProps['noDataConfig'] => ({ - pageTitle: PACKAGE_NOT_INSTALLED_TEXT.PAGE_TITLE, - solution: PACKAGE_NOT_INSTALLED_TEXT.SOLUTION, - // TODO: Add real docs link once we have it - docsLink: 'https://www.elastic.co/guide/index.html', - logo: 'logoSecurity', - actions: { - elasticAgent: { - href: cisIntegrationLink, - isDisabled: !cisIntegrationLink, - title: PACKAGE_NOT_INSTALLED_TEXT.BUTTON_TITLE, - description: PACKAGE_NOT_INSTALLED_TEXT.DESCRIPTION, - }, - }, -}); - -const DefaultLoading = () => ( - - - -); - -const DefaultError = (error: unknown) => ( - - -

- -

-
- {isCommonError(error) && ( - <> - -
- -
-
- -
- -
-
- - )} - - } - /> -); - export const CspPageTemplate = ({ - query, children, - loadingRender = DefaultLoading, - errorRender = DefaultError, ...kibanaPageTemplateProps -}: KibanaPageTemplateProps & { - loadingRender?: () => React.ReactNode; - errorRender?: (error: TError) => React.ReactNode; - query?: UseQueryResult; -}) => { - const cisKubernetesPackageInfo = useCisKubernetesIntegration(); - const cisIntegrationLink = useCISIntegrationLink(); - - const getNoDataConfig = (): KibanaPageTemplateProps['noDataConfig'] => { - if (cisKubernetesPackageInfo.data?.item.status !== 'installed') { - return getPackageNotInstalledNoDataConfig(cisIntegrationLink); - } - - // when query was successful, but data is undefined - if (query?.isSuccess && !query?.data) { - return kibanaPageTemplateProps.noDataConfig || DEFAULT_NO_DATA_CONFIG; - } - - return kibanaPageTemplateProps.noDataConfig; - }; - - const getTemplate = (): KibanaPageTemplateProps['template'] => { - if (query?.isLoading || query?.isError || cisKubernetesPackageInfo.isLoading) - return 'centeredContent'; - - return kibanaPageTemplateProps.template || 'default'; - }; - - const render = () => { - if (query?.isLoading || query?.isIdle || cisKubernetesPackageInfo.isLoading) { - return loadingRender(); - } - if (query?.isError) return errorRender(query.error); - if (query?.isSuccess) return children; - - return children; - }; - +}: KibanaPageTemplateProps) => { return ( - - - <>{render()} - + + {children} ); }; diff --git a/x-pack/plugins/cloud_security_posture/public/components/translations.ts b/x-pack/plugins/cloud_security_posture/public/components/translations.ts deleted file mode 100644 index 84d1ae489f8ea..0000000000000 --- a/x-pack/plugins/cloud_security_posture/public/components/translations.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { i18n } from '@kbn/i18n'; - -export const PACKAGE_NOT_INSTALLED_TEXT = { - PAGE_TITLE: i18n.translate('xpack.csp.cspPageTemplate.packageNotInstalled.pageTitle', { - defaultMessage: 'Install Integration to get started', - }), - SOLUTION: i18n.translate('xpack.csp.cspPageTemplate.packageNotInstalled.solutionNameLabel', { - defaultMessage: 'Cloud Security Posture', - }), - BUTTON_TITLE: i18n.translate('xpack.csp.cspPageTemplate.packageNotInstalled.buttonLabel', { - defaultMessage: 'Add a CIS integration', - }), - DESCRIPTION: i18n.translate('xpack.csp.cspPageTemplate.packageNotInstalled.description', { - defaultMessage: - 'Use our CIS Kubernetes Benchmark integration to measure your Kubernetes cluster setup against the CIS recommendations.', - }), -}; - -export const DEFAULT_NO_DATA_TEXT = { - PAGE_TITLE: i18n.translate('xpack.csp.cspPageTemplate.defaultNoDataConfig.pageTitle', { - defaultMessage: 'No data found', - }), - SOLUTION: i18n.translate('xpack.csp.cspPageTemplate.defaultNoDataConfig.solutionNameLabel', { - defaultMessage: 'Cloud Security Posture', - }), -}; - -export const CLOUD_SECURITY_POSTURE = i18n.translate('xpack.csp.cspPageTemplate.navigationTitle', { - defaultMessage: 'Cloud Security Posture', -}); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx index 4b25fe3c8b175..71362c2c92525 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { createReactQueryResponse } from '../../test/fixtures/react_query'; import React from 'react'; import { coreMock } from '@kbn/core/public/mocks'; import { render, screen } from '@testing-library/react'; @@ -13,7 +14,7 @@ import { ComplianceDashboard } from '..'; import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { useCisKubernetesIntegration } from '../../common/api/use_cis_kubernetes_integration'; import { useComplianceDashboardDataApi } from '../../common/api/use_compliance_dashboard_data_api'; -import { DASHBOARD_PAGE_HEADER, MISSING_FINDINGS_NO_DATA_CONFIG } from './test_subjects'; +import { DASHBOARD_CONTAINER, MISSING_FINDINGS_NO_DATA_CONFIG } from './test_subjects'; jest.mock('../../common/api/use_setup_status_api'); jest.mock('../../common/api/use_cis_kubernetes_integration'); @@ -196,17 +197,17 @@ describe('', () => { }; it('shows noDataConfig when latestFindingsIndexStatus is inapplicable', () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => ({ - data: { latestFindingsIndexStatus: 'inapplicable' }, - })); - (useComplianceDashboardDataApi as jest.Mock).mockImplementation(() => ({ - data: undefined, - })); + (useCspSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ status: 'success', data: 'inapplicable' }) + ); + (useComplianceDashboardDataApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ status: 'success', data: undefined }) + ); renderComplianceDashboardPage(); expect(screen.queryByTestId(MISSING_FINDINGS_NO_DATA_CONFIG)).toBeInTheDocument(); - expect(screen.queryByTestId(DASHBOARD_PAGE_HEADER)).not.toBeInTheDocument(); + expect(screen.queryByTestId(DASHBOARD_CONTAINER)).not.toBeInTheDocument(); }); it('shows dashboard when latestFindingsIndexStatus is applicable', () => { @@ -225,6 +226,6 @@ describe('', () => { renderComplianceDashboardPage(); expect(screen.queryByTestId(MISSING_FINDINGS_NO_DATA_CONFIG)).not.toBeInTheDocument(); - expect(screen.getByTestId(DASHBOARD_PAGE_HEADER)).toBeInTheDocument(); + expect(screen.getByTestId(DASHBOARD_CONTAINER)).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx index e0ba90441ea74..606d7671125da 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx @@ -7,10 +7,12 @@ import React from 'react'; import { EuiSpacer, EuiIcon } from '@elastic/eui'; -import { type KibanaPageTemplateProps } from '@kbn/kibana-react-plugin/public'; +import { NoDataPage } from '@kbn/kibana-react-plugin/public'; import { UseQueryResult } from 'react-query'; import { i18n } from '@kbn/i18n'; -import { DASHBOARD_PAGE_HEADER, MISSING_FINDINGS_NO_DATA_CONFIG } from './test_subjects'; +import { css } from '@emotion/react'; +import { CloudPosturePage } from '../../components/cloud_posture_page'; +import { DASHBOARD_CONTAINER, MISSING_FINDINGS_NO_DATA_CONFIG } from './test_subjects'; import { allNavigationItems } from '../../common/navigation/constants'; import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs'; import { SummarySection } from './dashboard_sections/summary_section'; @@ -19,31 +21,39 @@ import { useComplianceDashboardDataApi } from '../../common/api'; import { CspPageTemplate } from '../../components/csp_page_template'; import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; -const getNoDataConfig = (onClick: () => void): KibanaPageTemplateProps['noDataConfig'] => ({ - 'data-test-subj': MISSING_FINDINGS_NO_DATA_CONFIG, - pageTitle: i18n.translate('xpack.csp.dashboard.noDataConfig.pageTitle', { - defaultMessage: 'Cloud Posture Dashboard', - }), - solution: i18n.translate('xpack.csp.dashboard.noDataConfig.solutionNameTitle', { - defaultMessage: 'Cloud Security Posture', - }), - // TODO: Add real docs link once we have it - docsLink: 'https://www.elastic.co/guide/index.html', - logo: 'logoSecurity', - actions: { - dashboardNoDataCard: { - icon: , - onClick, - title: i18n.translate('xpack.csp.dashboard.noDataConfig.actionTitle', { - defaultMessage: 'Try Again', - }), - description: i18n.translate('xpack.csp.dashboard.noDataConfig.actionDescription', { - defaultMessage: - "The cloud posture dashboard can't be presented since there are no findings. This can happen due to the agent not being installed yet, or since data is still being processed.", - }), - }, - }, -}); +const NoData = ({ onClick }: { onClick: () => void }) => ( + , + onClick, + title: i18n.translate('xpack.csp.dashboard.noDataConfig.actionTitle', { + defaultMessage: 'Try Again', + }), + description: i18n.translate('xpack.csp.dashboard.noDataConfig.actionDescription', { + defaultMessage: + "The cloud posture dashboard can't be presented since there are no findings. This can happen due to the agent not being installed yet, or since data is still being processed.", + }), + }, + }} + /> +); export const ComplianceDashboard = () => { const getInfo = useCspSetupStatusApi(); @@ -51,6 +61,7 @@ export const ComplianceDashboard = () => { const getDashboardData = useComplianceDashboardDataApi({ enabled: isFindingsIndexApplicable, }); + useCspBreadcrumbs([allNavigationItems.dashboard]); const pageQuery: UseQueryResult = isFindingsIndexApplicable ? getDashboardData : getInfo; @@ -58,23 +69,24 @@ export const ComplianceDashboard = () => { return ( - {getDashboardData.data && ( - <> - - - - - - )} + + {isFindingsIndexApplicable ? ( +
+ + + + +
+ ) : ( + + )} +
); }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/test_subjects.ts b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/test_subjects.ts index 04cf7a1398114..6e0ca5773b7fc 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/test_subjects.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/test_subjects.ts @@ -6,4 +6,4 @@ */ export const MISSING_FINDINGS_NO_DATA_CONFIG = 'missing-findings-no-data-config'; -export const DASHBOARD_PAGE_HEADER = 'dashboard-page-header'; +export const DASHBOARD_CONTAINER = 'dashboard-container'; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx index 989408dc251b0..1604c77358596 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx @@ -22,6 +22,8 @@ import { useCisKubernetesIntegration } from '../../common/api/use_cis_kubernetes import type { DataView } from '@kbn/data-plugin/common'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; +import { discoverPluginMock } from '@kbn/discover-plugin/public/mocks'; +import type { DiscoverStart } from '@kbn/discover-plugin/public'; jest.mock('../../common/api/use_latest_findings_data_view'); jest.mock('../../common/api/use_cis_kubernetes_integration'); @@ -34,12 +36,14 @@ const Wrapper = ({ data = dataPluginMock.createStartContract(), unifiedSearch = unifiedSearchPluginMock.createStartContract(), charts = chartPluginMock.createStartContract(), + discover = discoverPluginMock.createStartContract(), }: { data: DataPublicPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; charts: ChartsPluginStart; + discover: DiscoverStart; }) => ( - + ); @@ -49,6 +53,7 @@ describe.skip('', () => { const data = dataPluginMock.createStartContract(); const unifiedSearch = unifiedSearchPluginMock.createStartContract(); const charts = chartPluginMock.createStartContract(); + const discover = discoverPluginMock.createStartContract(); const source = await data.search.searchSource.create(); (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ @@ -65,7 +70,9 @@ describe.skip('', () => { }), } as UseQueryResult); - render(); + render( + + ); expect(await screen.findByTestId(TEST_SUBJECTS.FINDINGS_CONTAINER)).toBeInTheDocument(); }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx index 599ab03545a2c..a8220c752b27f 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx @@ -7,6 +7,7 @@ import React from 'react'; import type { UseQueryResult } from 'react-query'; import { Redirect, Switch, Route, useLocation } from 'react-router-dom'; +import { CloudPosturePage } from '../../components/cloud_posture_page'; import { useFindingsEsPit } from './es_pit/use_findings_es_pit'; import { FindingsEsPitContext } from './es_pit/findings_es_pit_context'; import { useLatestFindingsDataView } from '../../common/api/use_latest_findings_data_view'; @@ -21,48 +22,50 @@ export const Findings = () => { // TODO: Consider splitting the PIT window so that each "group by" view has its own PIT const { pitQuery, pitIdRef, setPitId } = useFindingsEsPit('findings'); - let queryForPageTemplate: UseQueryResult = dataViewQuery; + let queryForSetupStatus: UseQueryResult = dataViewQuery; if (pitQuery.isError || pitQuery.isLoading || pitQuery.isIdle) { - queryForPageTemplate = pitQuery; + queryForSetupStatus = pitQuery; } return ( - - , - setPitId, - }} - > - - ( - - )} - /> - } - /> - } - /> - } - /> - - + + + , + setPitId, + }} + > + + ( + + )} + /> + } + /> + } + /> + } + /> + + + ); }; 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 5c29e40d28436..94d221ddf9af7 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 @@ -5,18 +5,28 @@ * 2.0. */ -import { EuiAccordion, EuiDescriptionList, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; +import { + EuiAccordion, + EuiDescriptionList, + EuiLink, + EuiPanel, + EuiSpacer, + EuiText, +} from '@elastic/eui'; import React, { useMemo } from 'react'; import moment from 'moment'; import type { EuiDescriptionListProps, EuiAccordionProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { LATEST_FINDINGS_INDEX_DEFAULT_NS } from '../../../../common/constants'; +import { useLatestFindingsDataView } from '../../../common/api/use_latest_findings_data_view'; +import { useKibana } from '../../../common/hooks/use_kibana'; import { CspFinding } from '../types'; import { CisKubernetesIcons, Markdown, CodeBlock } from './findings_flyout'; type Accordion = Pick & Pick; -const getDetailsList = (data: CspFinding) => [ +const getDetailsList = (data: CspFinding, discoverIndexLink: string | undefined) => [ { title: i18n.translate('xpack.csp.findings.findingsFlyout.overviewTab.ruleNameTitle', { defaultMessage: 'Rule Name', @@ -47,6 +57,16 @@ const getDetailsList = (data: CspFinding) => [ }), description: data.rule.section, }, + { + title: i18n.translate('xpack.csp.findings.findingsFlyout.overviewTab.indexTitle', { + defaultMessage: 'Index', + }), + description: discoverIndexLink ? ( + {LATEST_FINDINGS_INDEX_DEFAULT_NS} + ) : ( + LATEST_FINDINGS_INDEX_DEFAULT_NS + ), + }, ]; export const getRemediationList = (rule: CspFinding['rule']) => [ @@ -99,6 +119,19 @@ const getEvidenceList = ({ result }: CspFinding) => ].filter(Boolean) as EuiDescriptionListProps['listItems']; export const OverviewTab = ({ data }: { data: CspFinding }) => { + const { + services: { discover }, + } = useKibana(); + const latestFindingsDataView = useLatestFindingsDataView(); + + const discoverIndexLink = useMemo( + () => + discover.locator?.getRedirectUrl({ + indexPatternId: latestFindingsDataView.data?.id, + }), + [discover.locator, latestFindingsDataView.data?.id] + ); + const accordions: Accordion[] = useMemo( () => [ { @@ -107,7 +140,7 @@ export const OverviewTab = ({ data }: { data: CspFinding }) => { defaultMessage: 'Details', }), id: 'detailsAccordion', - listItems: getDetailsList(data), + listItems: getDetailsList(data, discoverIndexLink), }, { initialIsOpen: true, @@ -127,7 +160,7 @@ export const OverviewTab = ({ data }: { data: CspFinding }) => { listItems: getEvidenceList(data), }, ], - [data] + [data, discoverIndexLink] ); return ( 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 3e9fd0941495e..c74b928100d8b 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 @@ -22,6 +22,7 @@ import { buildEsQuery } from '@kbn/es-query'; import { getPaginationQuery } from '../utils'; import { FindingsEsPitContext } from '../es_pit/findings_es_pit_context'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; +import { discoverPluginMock } from '@kbn/discover-plugin/public/mocks'; jest.mock('../../../common/api/use_latest_findings_data_view'); jest.mock('../../../common/api/use_cis_kubernetes_integration'); @@ -66,6 +67,7 @@ describe('', () => { data: dataMock, unifiedSearch: unifiedSearchPluginMock.createStartContract(), charts: chartPluginMock.createStartContract(), + discover: discoverPluginMock.createStartContract(), }} > diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx index 6b9953e429d9f..65de13726ced3 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx @@ -7,19 +7,18 @@ import React, { useMemo } from 'react'; import { generatePath, Link, RouteComponentProps } from 'react-router-dom'; -import { EuiTextColor, EuiEmptyPrompt, EuiButtonEmpty, EuiFlexGroup } from '@elastic/eui'; -import * as t from 'io-ts'; -import type { KibanaPageTemplateProps } from '@kbn/kibana-react-plugin/public'; +import { EuiTextColor, EuiButtonEmpty, EuiFlexGroup } from '@elastic/eui'; +import type { KibanaPageTemplateProps } from '@kbn/shared-ux-components'; import { FormattedMessage } from '@kbn/i18n-react'; import { pagePathGetters } from '@kbn/fleet-plugin/public'; import { RulesContainer, type PageUrlParams } from './rules_container'; import { allNavigationItems } from '../../common/navigation/constants'; import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs'; import { CspNavigationItem } from '../../common/navigation/types'; -import { extractErrorMessage } from '../../../common/utils/helpers'; import { useCspIntegrationInfo } from './use_csp_integration'; import { CspPageTemplate } from '../../components/csp_page_template'; import { useKibana } from '../../common/hooks/use_kibana'; +import { CloudPosturePage } from '../../components/cloud_posture_page'; const getRulesBreadcrumbs = (name?: string): CspNavigationItem[] => [allNavigationItems.benchmarks, { ...allNavigationItems.rules, name }].filter( @@ -93,34 +92,10 @@ export const Rules = ({ match: { params } }: RouteComponentProps) ); return ( - } - > - + + + + ); }; - -// react-query puts the response data on the 'error' object -const bodyError = t.type({ - body: t.type({ - message: t.string, - }), -}); - -const extractErrorBodyMessage = (err: unknown) => { - if (bodyError.is(err)) return err.body.message; - return extractErrorMessage(err); -}; - -const RulesErrorPrompt = ({ error }: { error: string }) => ( - {error}, - }} - /> -); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx index 0acf17dc8005f..2056173d99f88 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; -import { LOADING_STATE_TEST_SUBJECT } from '../../components/csp_page_template'; import { Rules } from '.'; import { render, screen } from '@testing-library/react'; import { QueryClient } from 'react-query'; @@ -79,33 +78,6 @@ describe('', () => { expect(useCspIntegrationInfo).toHaveBeenCalledWith(params); }); - it('displays error state when request had an error', async () => { - const Component = getTestComponent({ packagePolicyId: '1', policyId: '2' }); - const request = createReactQueryResponse({ - status: 'error', - error: new Error('some error message'), - }); - - (useCspIntegrationInfo as jest.Mock).mockReturnValue(request); - - render(); - - expect(await screen.findByText(request.error?.message!)).toBeInTheDocument(); - }); - - it('displays loading state when request is pending', () => { - const Component = getTestComponent({ packagePolicyId: '21', policyId: '22' }); - const request = createReactQueryResponse({ - status: 'loading', - }); - - (useCspIntegrationInfo as jest.Mock).mockReturnValue(request); - - render(); - - expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); - }); - it('displays success state when result request is resolved', async () => { const Component = getTestComponent({ packagePolicyId: '21', policyId: '22' }); const request = createReactQueryResponse({ diff --git a/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx b/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx index d0a925069a884..7aaa00f7923b2 100755 --- a/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx +++ b/x-pack/plugins/cloud_security_posture/public/test/test_provider.tsx @@ -14,6 +14,7 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; +import { discoverPluginMock } from '@kbn/discover-plugin/public/mocks'; import type { CspAppDeps } from '../application/app'; export const TestProvider: React.FC> = ({ @@ -22,6 +23,7 @@ export const TestProvider: React.FC> = ({ data: dataPluginMock.createStartContract(), unifiedSearch: unifiedSearchPluginMock.createStartContract(), charts: chartPluginMock.createStartContract(), + discover: discoverPluginMock.createStartContract(), }, params = coreMock.createAppMountParameters(), children, diff --git a/x-pack/plugins/cloud_security_posture/public/types.ts b/x-pack/plugins/cloud_security_posture/public/types.ts index f5fbb2766e6b9..dbb69b0d65e65 100755 --- a/x-pack/plugins/cloud_security_posture/public/types.ts +++ b/x-pack/plugins/cloud_security_posture/public/types.ts @@ -8,6 +8,7 @@ import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; +import type { DiscoverStart } from '@kbn/discover-plugin/public'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface CspClientPluginSetup {} @@ -26,5 +27,6 @@ export interface CspClientPluginStartDeps { data: DataPublicPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; charts: ChartsPluginStart; + discover: DiscoverStart; // optional } diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index 55dfcd2fa259a..9f66386eb4144 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -356,7 +356,6 @@ describe('benchmarks API', () => { it('should build benchmark entry agent policy and package policy', async () => { const packagePolicy = createPackagePolicyMock(); const agentPolicy = createMockAgentPolicy(); - // @ts-expect-error agentPolicy.agents = 3; const cspRulesStatus = { diff --git a/x-pack/plugins/data_visualizer/common/constants.ts b/x-pack/plugins/data_visualizer/common/constants.ts index f31a42cc7784c..1923613d72c58 100644 --- a/x-pack/plugins/data_visualizer/common/constants.ts +++ b/x-pack/plugins/data_visualizer/common/constants.ts @@ -29,16 +29,17 @@ export const FILE_FORMATS = { // XML: 'xml', }; -export const JOB_FIELD_TYPES = { +export const SUPPORTED_FIELD_TYPES = { BOOLEAN: 'boolean', DATE: 'date', GEO_POINT: 'geo_point', GEO_SHAPE: 'geo_shape', + HISTOGRAM: 'histogram', IP: 'ip', KEYWORD: 'keyword', NUMBER: 'number', TEXT: 'text', - HISTOGRAM: 'histogram', + VERSION: 'version', UNKNOWN: 'unknown', } as const; diff --git a/x-pack/plugins/data_visualizer/common/types/field_request_config.ts b/x-pack/plugins/data_visualizer/common/types/field_request_config.ts index 5f21748575831..4db8cc8aa7996 100644 --- a/x-pack/plugins/data_visualizer/common/types/field_request_config.ts +++ b/x-pack/plugins/data_visualizer/common/types/field_request_config.ts @@ -29,6 +29,16 @@ export interface DocumentCounts { interval?: number; } +export interface LatLongExample { + lat: number; + lon: number; +} + +export interface GeoPointExample { + coordinates: number[]; + type?: string; +} + export interface FieldVisStats { error?: Error; cardinality?: number; @@ -56,7 +66,7 @@ export interface FieldVisStats { topValues?: Array<{ key: number | string; doc_count: number }>; topValuesSampleSize?: number; topValuesSamplerShardSize?: number; - examples?: Array; + examples?: Array; timeRangeEarliest?: number; timeRangeLatest?: number; } diff --git a/x-pack/plugins/data_visualizer/common/types/job_field_type.ts b/x-pack/plugins/data_visualizer/common/types/job_field_type.ts index ecb6ade035695..bc44361a416c7 100644 --- a/x-pack/plugins/data_visualizer/common/types/job_field_type.ts +++ b/x-pack/plugins/data_visualizer/common/types/job_field_type.ts @@ -5,5 +5,5 @@ * 2.0. */ -import { JOB_FIELD_TYPES } from '../constants'; -export type JobFieldType = typeof JOB_FIELD_TYPES[keyof typeof JOB_FIELD_TYPES]; +import { SUPPORTED_FIELD_TYPES } from '../constants'; +export type JobFieldType = typeof SUPPORTED_FIELD_TYPES[keyof typeof SUPPORTED_FIELD_TYPES]; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/examples_list/examples_list.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/examples_list/examples_list.tsx index c4792b314b6a6..71722faab8829 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/examples_list/examples_list.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/examples_list/examples_list.tsx @@ -10,12 +10,19 @@ import React, { FC } from 'react'; import { EuiListGroup, EuiListGroupItem } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; +import { GeoPointExample } from '../../../../../common/types/field_request_config'; import { ExpandedRowFieldHeader } from '../stats_table/components/expanded_row_field_header'; import { ExpandedRowPanel } from '../stats_table/components/field_data_expanded_row/expanded_row_panel'; + interface Props { - examples: Array; + examples: Array; } +const EMPTY_EXAMPLE = i18n.translate( + 'xpack.dataVisualizer.dataGrid.field.examplesList.emptyExampleMessage', + { defaultMessage: '(empty)' } +); export const ExamplesList: FC = ({ examples }) => { if (examples === undefined || examples === null || !Array.isArray(examples)) { return null; @@ -34,7 +41,13 @@ export const ExamplesList: FC = ({ examples }) => { ); }); diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/file_based_expanded_row.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/file_based_expanded_row.tsx index 07e5d01e71d9b..ebe37dda153f4 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/file_based_expanded_row.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/file_based_expanded_row.tsx @@ -16,7 +16,7 @@ import { NumberContent, } from '../stats_table/components/field_data_expanded_row'; import { GeoPointContent } from './geo_point_content/geo_point_content'; -import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants'; import type { FileBasedFieldVisConfig } from '../../../../../common/types/field_vis_config'; export const FileBasedDataVisualizerExpandedRow = ({ item }: { item: FileBasedFieldVisConfig }) => { @@ -25,25 +25,26 @@ export const FileBasedDataVisualizerExpandedRow = ({ item }: { item: FileBasedFi function getCardContent() { switch (type) { - case JOB_FIELD_TYPES.NUMBER: + case SUPPORTED_FIELD_TYPES.NUMBER: return ; - case JOB_FIELD_TYPES.BOOLEAN: + case SUPPORTED_FIELD_TYPES.BOOLEAN: return ; - case JOB_FIELD_TYPES.DATE: + case SUPPORTED_FIELD_TYPES.DATE: return ; - case JOB_FIELD_TYPES.GEO_POINT: + case SUPPORTED_FIELD_TYPES.GEO_POINT: return ; - case JOB_FIELD_TYPES.IP: + case SUPPORTED_FIELD_TYPES.IP: return ; - case JOB_FIELD_TYPES.KEYWORD: + case SUPPORTED_FIELD_TYPES.KEYWORD: + case SUPPORTED_FIELD_TYPES.VERSION: return ; - case JOB_FIELD_TYPES.TEXT: + case SUPPORTED_FIELD_TYPES.TEXT: return ; default: diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx index 8a0b1d7a3dfe6..f12b65569be1c 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import React, { FC, useEffect, useState } from 'react'; import { DataView } from '@kbn/data-views-plugin/public'; import { ES_GEO_FIELD_TYPE, LayerDescriptor } from '@kbn/maps-plugin/common'; @@ -14,7 +13,7 @@ import { DocumentStatsTable } from '../../stats_table/components/field_data_expa import { ExamplesList } from '../../examples_list'; import { FieldVisConfig } from '../../stats_table/types'; import { useDataVisualizerKibana } from '../../../../kibana_context'; -import { JOB_FIELD_TYPES } from '../../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../../common/constants'; import { EmbeddedMapComponent } from '../../embedded_map'; import { ExpandedRowPanel } from '../../stats_table/components/field_data_expanded_row/expanded_row_panel'; @@ -36,7 +35,8 @@ export const GeoPointContentWithMap: FC<{ dataView?.id !== undefined && config !== undefined && config.fieldName !== undefined && - (config.type === JOB_FIELD_TYPES.GEO_POINT || config.type === JOB_FIELD_TYPES.GEO_SHAPE) + (config.type === SUPPORTED_FIELD_TYPES.GEO_POINT || + config.type === SUPPORTED_FIELD_TYPES.GEO_SHAPE) ) { const params = { indexPatternId: dataView.id, @@ -64,7 +64,7 @@ export const GeoPointContentWithMap: FC<{ return ( - + diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx index c108ca238de8a..e770a4c6bba7a 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; import { GeoPointContentWithMap } from './geo_point_content_with_map'; -import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants'; import { BooleanContent, DateContent, @@ -51,17 +51,17 @@ export const IndexBasedDataVisualizerExpandedRow = ({ } switch (type) { - case JOB_FIELD_TYPES.NUMBER: + case SUPPORTED_FIELD_TYPES.NUMBER: return ; - case JOB_FIELD_TYPES.BOOLEAN: - return ; + case SUPPORTED_FIELD_TYPES.BOOLEAN: + return ; - case JOB_FIELD_TYPES.DATE: + case SUPPORTED_FIELD_TYPES.DATE: return ; - case JOB_FIELD_TYPES.GEO_POINT: - case JOB_FIELD_TYPES.GEO_SHAPE: + case SUPPORTED_FIELD_TYPES.GEO_POINT: + case SUPPORTED_FIELD_TYPES.GEO_SHAPE: return ( ); - case JOB_FIELD_TYPES.IP: + case SUPPORTED_FIELD_TYPES.IP: return ; - case JOB_FIELD_TYPES.KEYWORD: + case SUPPORTED_FIELD_TYPES.KEYWORD: + case SUPPORTED_FIELD_TYPES.VERSION: return ; - case JOB_FIELD_TYPES.TEXT: + case SUPPORTED_FIELD_TYPES.TEXT: return ; default: diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts index 73e69b00132d3..314856e07554f 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts @@ -18,7 +18,7 @@ import { dataVisualizerRefresh$, Refresh, } from '../../../../index_data_visualizer/services/timefilter_refresh_service'; -import { JOB_FIELD_TYPES } from '../../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../../common/constants'; import { APP_ID } from '../../../../../../common/constants'; export function getActions( @@ -80,7 +80,10 @@ export function getActions( type: 'icon', icon: 'gisApp', available: (item: FieldVisConfig) => { - return item.type === JOB_FIELD_TYPES.GEO_POINT || item.type === JOB_FIELD_TYPES.GEO_SHAPE; + return ( + item.type === SUPPORTED_FIELD_TYPES.GEO_POINT || + item.type === SUPPORTED_FIELD_TYPES.GEO_SHAPE + ); }, onClick: async (item: FieldVisConfig) => { if (services?.uiActions && dataView) { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts index 731499cee2f89..034f7037fc29a 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts @@ -19,7 +19,7 @@ import type { import { DOCUMENT_FIELD_NAME as RECORDS_FIELD } from '@kbn/lens-plugin/common/constants'; import type { CombinedQuery } from '../../../../index_data_visualizer/types/combined_query'; import { FieldVisConfig } from '../../stats_table/types'; -import { JOB_FIELD_TYPES } from '../../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../../common/constants'; interface ColumnsAndLayer { columns: Record; @@ -200,19 +200,20 @@ export function getBooleanSettings(item: FieldVisConfig) { export function getCompatibleLensDataType(type: FieldVisConfig['type']): string | undefined { let lensType: string | undefined; switch (type) { - case JOB_FIELD_TYPES.KEYWORD: + case SUPPORTED_FIELD_TYPES.KEYWORD: + case SUPPORTED_FIELD_TYPES.VERSION: lensType = 'string'; break; - case JOB_FIELD_TYPES.DATE: + case SUPPORTED_FIELD_TYPES.DATE: lensType = 'date'; break; - case JOB_FIELD_TYPES.NUMBER: + case SUPPORTED_FIELD_TYPES.NUMBER: lensType = 'number'; break; - case JOB_FIELD_TYPES.IP: + case SUPPORTED_FIELD_TYPES.IP: lensType = 'ip'; break; - case JOB_FIELD_TYPES.BOOLEAN: + case SUPPORTED_FIELD_TYPES.BOOLEAN: lensType = 'string'; break; default: @@ -228,16 +229,20 @@ function getColumnsAndLayer( ): ColumnsAndLayer | undefined { if (item.fieldName === undefined) return; - if (fieldType === JOB_FIELD_TYPES.DATE) { + if (fieldType === SUPPORTED_FIELD_TYPES.DATE) { return getDateSettings(item); } - if (fieldType === JOB_FIELD_TYPES.NUMBER) { + if (fieldType === SUPPORTED_FIELD_TYPES.NUMBER) { return getNumberSettings(item, defaultDataView); } - if (fieldType === JOB_FIELD_TYPES.IP || fieldType === JOB_FIELD_TYPES.KEYWORD) { + if ( + fieldType === SUPPORTED_FIELD_TYPES.IP || + fieldType === SUPPORTED_FIELD_TYPES.KEYWORD || + fieldType === SUPPORTED_FIELD_TYPES.VERSION + ) { return getKeywordSettings(item); } - if (fieldType === JOB_FIELD_TYPES.BOOLEAN) { + if (fieldType === SUPPORTED_FIELD_TYPES.BOOLEAN) { return getBooleanSettings(item); } } diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.test.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.test.tsx index 874cdaa670c49..9962937fa80dc 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.test.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_type_icon/field_type_icon.test.tsx @@ -9,12 +9,12 @@ import React from 'react'; import { mount, shallow } from 'enzyme'; import { FieldTypeIcon } from './field_type_icon'; -import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants'; describe('FieldTypeIcon', () => { test(`render component when type matches a field type`, () => { const typeIconComponent = shallow( - + ); expect(typeIconComponent).toMatchSnapshot(); }); @@ -24,7 +24,7 @@ describe('FieldTypeIcon', () => { jest.useFakeTimers(); const typeIconComponent = mount( - + ); expect(typeIconComponent.find('EuiToolTip').children()).toHaveLength(1); diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/create_fields.ts b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/create_fields.ts index 05d07111c80ac..2ac163104eea5 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/create_fields.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/create_fields.ts @@ -8,7 +8,7 @@ import { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; import { getFieldNames, getSupportedFieldType } from './get_field_names'; import { FileBasedFieldVisConfig } from '../stats_table/types'; -import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants'; import { roundToDecimalPlace } from '../utils'; export function createFields(results: FindFileStructureResponse) { @@ -28,20 +28,20 @@ export function createFields(results: FindFileStructureResponse) { if (fieldStats[name] !== undefined) { const field: FileBasedFieldVisConfig = { fieldName: name, - type: JOB_FIELD_TYPES.UNKNOWN, + type: SUPPORTED_FIELD_TYPES.UNKNOWN, }; const f = fieldStats[name]; const m = mappings.properties[name]; // sometimes the timestamp field is not in the mappings, and so our // collection of fields will be missing a time field with a type of date - if (name === timestampField && field.type === JOB_FIELD_TYPES.UNKNOWN) { - field.type = JOB_FIELD_TYPES.DATE; + if (name === timestampField && field.type === SUPPORTED_FIELD_TYPES.UNKNOWN) { + field.type = SUPPORTED_FIELD_TYPES.DATE; } if (m !== undefined) { field.type = getSupportedFieldType(m.type); - if (field.type === JOB_FIELD_TYPES.NUMBER) { + if (field.type === SUPPORTED_FIELD_TYPES.NUMBER) { numericFieldsCount += 1; } if (m.format !== undefined) { @@ -71,7 +71,7 @@ export function createFields(results: FindFileStructureResponse) { } if (f.top_hits !== undefined) { - if (field.type === JOB_FIELD_TYPES.TEXT) { + if (field.type === SUPPORTED_FIELD_TYPES.TEXT) { _stats = { ..._stats, examples: f.top_hits.map((hit) => hit.value), @@ -84,7 +84,7 @@ export function createFields(results: FindFileStructureResponse) { } } - if (field.type === JOB_FIELD_TYPES.DATE) { + if (field.type === SUPPORTED_FIELD_TYPES.DATE) { _stats = { ..._stats, earliest: f.earliest, @@ -99,9 +99,9 @@ export function createFields(results: FindFileStructureResponse) { // this could be the message field for a semi-structured log file or a // field which the endpoint has not been able to work out any information for const type = - mappings.properties[name] && mappings.properties[name].type === JOB_FIELD_TYPES.TEXT - ? JOB_FIELD_TYPES.TEXT - : JOB_FIELD_TYPES.UNKNOWN; + mappings.properties[name] && mappings.properties[name].type === SUPPORTED_FIELD_TYPES.TEXT + ? SUPPORTED_FIELD_TYPES.TEXT + : SUPPORTED_FIELD_TYPES.UNKNOWN; return { fieldName: name, diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/filter_fields.ts b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/filter_fields.ts index 145a8fa5f8867..4ca65eec6635b 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/filter_fields.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/filter_fields.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants'; interface CommonFieldConfig { type: string; @@ -32,6 +32,6 @@ export function filterFields( return { filteredFields: items, visibleFieldsCount: items.length, - visibleMetricsCount: items.filter((d) => d.type === JOB_FIELD_TYPES.NUMBER).length, + visibleMetricsCount: items.filter((d) => d.type === SUPPORTED_FIELD_TYPES.NUMBER).length, }; } diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/get_field_names.ts b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/get_field_names.ts index b6868ced4de69..b0750278ab9e3 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/get_field_names.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/fields_stats_grid/get_field_names.ts @@ -9,7 +9,7 @@ import { difference } from 'lodash'; import { ES_FIELD_TYPES } from '@kbn/data-plugin/common'; import type { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; import type { JobFieldType } from '../../../../../common/types'; -import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants'; export function getFieldNames(results: FindFileStructureResponse) { const { mappings, field_stats: fieldStats, column_names: columnNames } = results; @@ -44,11 +44,11 @@ export function getSupportedFieldType(type: string): JobFieldType { case ES_FIELD_TYPES.LONG: case ES_FIELD_TYPES.SHORT: case ES_FIELD_TYPES.UNSIGNED_LONG: - return JOB_FIELD_TYPES.NUMBER; + return SUPPORTED_FIELD_TYPES.NUMBER; case ES_FIELD_TYPES.DATE: case ES_FIELD_TYPES.DATE_NANOS: - return JOB_FIELD_TYPES.DATE; + return SUPPORTED_FIELD_TYPES.DATE; default: return type as JobFieldType; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/_index.scss b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/_index.scss index 7ac8aa4365732..5aaf24b82a1a6 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/_index.scss +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/_index.scss @@ -31,9 +31,8 @@ $panelWidthL: #{'max(40%, 450px)'}; } .euiTableRow > .euiTableRowCell { - border-bottom: 0; - border-top: $euiBorderThin; - + border-top: 0; + border-bottom: $euiBorderThin; } .euiTableCellContent { diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_expanded_row/boolean_content.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_expanded_row/boolean_content.tsx index 907bc6166afff..210f69c435a45 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_expanded_row/boolean_content.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_expanded_row/boolean_content.tsx @@ -5,18 +5,13 @@ * 2.0. */ -import React, { FC, ReactNode, useMemo } from 'react'; -import { - EuiBasicTable, - EuiSpacer, - RIGHT_ALIGNMENT, - LEFT_ALIGNMENT, - HorizontalAlignment, -} from '@elastic/eui'; +import React, { FC, useMemo } from 'react'; +import { EuiSpacer } from '@elastic/eui'; import { Axis, BarSeries, Chart, Settings, ScaleType } from '@elastic/charts'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; +import { TopValues } from '../../../top_values'; import type { FieldDataRowProps } from '../../types/field_data_row'; import { ExpandedRowFieldHeader } from '../expanded_row_field_header'; import { getTFPercentage } from '../../utils'; @@ -44,72 +39,42 @@ function getFormattedValue(value: number, totalCount: number): string { const BOOLEAN_DISTRIBUTION_CHART_HEIGHT = 70; -export const BooleanContent: FC = ({ config }) => { +export const BooleanContent: FC = ({ config, onAddFilter }) => { const fieldFormat = 'fieldFormat' in config ? config.fieldFormat : undefined; const formattedPercentages = useMemo(() => getTFPercentage(config), [config]); const theme = useDataVizChartTheme(); if (!formattedPercentages) return null; const { trueCount, falseCount, count } = formattedPercentages; - const summaryTableItems = [ - { - function: 'true', - display: ( - - ), - value: getFormattedValue(trueCount, count), - }, - { - function: 'false', - display: ( - - ), - value: getFormattedValue(falseCount, count), - }, - ]; - const summaryTableColumns = [ - { - field: 'function', - name: '', - render: (_: string, summaryItem: { display: ReactNode }) => summaryItem.display, - width: '25px', - align: LEFT_ALIGNMENT as HorizontalAlignment, - }, - { - field: 'value', - name: '', - render: (v: string) => {v}, - align: RIGHT_ALIGNMENT as HorizontalAlignment, - }, - ]; - - const summaryTableTitle = i18n.translate( - 'xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.summaryTableTitle', - { - defaultMessage: 'Summary', - } - ); - + const stats = { + ...config.stats, + topValues: [ + { + key: i18n.translate( + 'xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.trueCountLabel', + { defaultMessage: 'true' } + ), + doc_count: trueCount ?? 0, + }, + { + key: i18n.translate( + 'xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.falseCountLabel', + { defaultMessage: 'false' } + ), + doc_count: falseCount ?? 0, + }, + ], + }; return ( - - {summaryTableTitle} - - + diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx index a2d61d104d138..8b38563591e3d 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/data_visualizer_stats_table.tsx @@ -20,11 +20,13 @@ import { RIGHT_ALIGNMENT, EuiResizeObserver, EuiLoadingSpinner, + useEuiTheme, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { EuiTableComputedColumnType } from '@elastic/eui/src/components/basic_table/table_types'; import { throttle } from 'lodash'; -import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import { css } from '@emotion/react'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants'; import type { JobFieldType, DataVisualizerTableState } from '../../../../../common/types'; import { DocumentStat } from './components/field_data_row/document_stats'; import { IndexBasedNumberContentPreview } from './components/field_data_row/number_content_preview'; @@ -70,6 +72,8 @@ export const DataVisualizerTable = ({ onChange, loading, }: DataVisualizerTableProps) => { + const { euiTheme } = useEuiTheme(); + const [expandedRowItemIds, setExpandedRowItemIds] = useState([]); const [expandAll, setExpandAll] = useState(false); @@ -289,13 +293,14 @@ export const DataVisualizerTable = ({ } if ( - (item.type === JOB_FIELD_TYPES.KEYWORD || item.type === JOB_FIELD_TYPES.IP) && + (item.type === SUPPORTED_FIELD_TYPES.KEYWORD || + item.type === SUPPORTED_FIELD_TYPES.IP) && item.stats?.topValues !== undefined ) { return ; } - if (item.type === JOB_FIELD_TYPES.NUMBER) { + if (item.type === SUPPORTED_FIELD_TYPES.NUMBER) { if (isIndexBasedFieldVisConfig(item) && item.stats?.distribution !== undefined) { // If the cardinality is only low, show the top values instead of a distribution chart return item.stats?.distribution?.percentiles.length <= 2 ? ( @@ -308,7 +313,7 @@ export const DataVisualizerTable = ({ } } - if (item.type === JOB_FIELD_TYPES.BOOLEAN) { + if (item.type === SUPPORTED_FIELD_TYPES.BOOLEAN) { return ; } @@ -361,6 +366,18 @@ export const DataVisualizerTable = ({ rowProps={(item) => ({ 'data-test-subj': `dataVisualizerRow row-${item.fieldName}`, })} + css={css` + thead { + position: sticky; + inset-block-start: 0; + z-index: 1; + background-color: ${euiTheme.colors.emptyShade}; + box-shadow: inset 0 0px 0, inset 0 -1px 0 ${euiTheme.border.color}; + } + .euiTableRow > .euiTableRowCel { + border-top: 0px; + } + `} />
)} diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.test.ts b/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.test.ts new file mode 100644 index 0000000000000..bc1c489cd77a0 --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.test.ts @@ -0,0 +1,153 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getUniqGeoOrStrExamples } from './example_utils'; + +describe('example utils', () => { + describe('getUniqGeoOrStrExamples', () => { + test('should remove duplicated strings up to maxExamples', () => { + expect( + getUniqGeoOrStrExamples( + [ + 'deb', + '', + 'css', + 'deb', + '', + '', + 'deb', + 'gz', + '', + 'gz', + '', + 'deb', + 'gz', + 'deb', + '', + 'deb', + 'deb', + '', + 'gz', + 'gz', + ], + 20 + ) + ).toMatchObject(['deb', '', 'css', 'gz']); + expect( + getUniqGeoOrStrExamples( + [ + 'deb', + '', + 'css', + 'deb', + '', + '', + 'deb', + 'gz', + '', + 'gz', + '', + 'deb', + 'gz', + 'deb', + '', + 'deb', + 'deb', + '', + 'gz', + 'gz', + ], + 2 + ) + ).toMatchObject(['deb', '']); + }); + + test('should remove duplicated coordinates up to maxExamples', () => { + expect( + getUniqGeoOrStrExamples([ + { coordinates: [0.1, 2343], type: 'Point' }, + { coordinates: [0.1, 2343], type: 'Point' }, + { coordinates: [0.1, 2343], type: 'Point' }, + { coordinates: [0.1, 2343], type: 'Shape' }, + { coordinates: [0.1, 2343] }, + { coordinates: [4321, 2343], type: 'Point' }, + { coordinates: [4321, 2343], type: 'Point' }, + ]) + ).toMatchObject([ + { + coordinates: [0.1, 2343], + type: 'Point', + }, + { + coordinates: [0.1, 2343], + type: 'Shape', + }, + { + coordinates: [0.1, 2343], + }, + { + coordinates: [4321, 2343], + type: 'Point', + }, + ]); + expect( + getUniqGeoOrStrExamples([ + { coordinates: [1, 2, 3], type: 'Point' }, + { coordinates: [1, 2, 3], type: 'Point' }, + { coordinates: [1, 2, 3], type: 'Point' }, + { coordinates: [1, 2, 3, 4], type: 'Shape' }, + { coordinates: [1, 2, 3, 4] }, + ]) + ).toMatchObject([ + { + coordinates: [1, 2, 3], + type: 'Point', + }, + { coordinates: [1, 2, 3, 4], type: 'Shape' }, + { coordinates: [1, 2, 3, 4] }, + ]); + }); + + test('should remove duplicated lon/lat coordinates up to maxExamples', () => { + expect( + getUniqGeoOrStrExamples([ + { lon: 0.1, lat: 2343 }, + { lon: 0.1, lat: 2343 }, + { lon: 0.1, lat: 2343 }, + { lon: 0.1, lat: 2343 }, + { lon: 0.1, lat: 2343 }, + { lon: 4321, lat: 2343 }, + { lon: 4321, lat: 2343 }, + ]) + ).toMatchObject([ + { lon: 0.1, lat: 2343 }, + { lon: 4321, lat: 2343 }, + ]); + expect( + getUniqGeoOrStrExamples( + [ + { lon: 1, lat: 2 }, + { lon: 1, lat: 2 }, + { lon: 2, lat: 3 }, + { lon: 2, lat: 3 }, + { lon: 3, lat: 4 }, + { lon: 3, lat: 4 }, + { lon: 4, lat: 5 }, + { lon: 4, lat: 5 }, + { lon: 5, lat: 6 }, + { lon: 5, lat: 6 }, + ], + 3 + ) + ).toMatchObject([ + { lon: 1, lat: 2 }, + { lon: 2, lat: 3 }, + { lon: 3, lat: 4 }, + ]); + }); + }); +}); diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.ts b/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.ts new file mode 100644 index 0000000000000..cc4a9a3ca9bfa --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/common/util/example_utils.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import { isDefined } from './is_defined'; +import { GeoPointExample, LatLongExample } from '../../../../common/types/field_request_config'; + +export function isGeoPointExample(arg: unknown): arg is GeoPointExample { + return isPopulatedObject(arg, ['coordinates']) && Array.isArray(arg.coordinates); +} + +export function isLonLatExample(arg: unknown): arg is LatLongExample { + return isPopulatedObject(arg, ['lon', 'lat']); +} + +export function getUniqGeoOrStrExamples( + examples: Array | undefined, + maxExamples = 10 +): Array { + const uniqueCoordinates: Array = []; + if (!isDefined(examples)) return uniqueCoordinates; + for (let i = 0; i < examples.length; i++) { + const example = examples[i]; + if (typeof example === 'string' && uniqueCoordinates.indexOf(example) === -1) { + uniqueCoordinates.push(example); + } else { + if ( + isGeoPointExample(example) && + uniqueCoordinates.findIndex( + (c) => + isGeoPointExample(c) && + c.type === example.type && + example.coordinates.every((coord, idx) => coord === c.coordinates[idx]) + ) === -1 + ) { + uniqueCoordinates.push(example); + } + + if ( + isLonLatExample(example) && + uniqueCoordinates.findIndex( + (c) => isLonLatExample(c) && example.lon === c.lon && example.lat === c.lat + ) === -1 + ) { + uniqueCoordinates.push(example); + } + } + if (uniqueCoordinates.length === maxExamples) { + return uniqueCoordinates; + } + } + + return uniqueCoordinates; +} diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.test.ts b/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.test.ts index 8f9e4ffd3b898..0f3ae62eae209 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.test.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.test.ts @@ -5,24 +5,26 @@ * 2.0. */ -import { JOB_FIELD_TYPES } from '../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../common/constants'; import { getJobTypeLabel, jobTypeLabels } from './field_types_utils'; describe('field type utils', () => { describe('getJobTypeLabel: Getting a field type aria label by passing what it is stored in constants', () => { - test('should returns all JOB_FIELD_TYPES labels exactly as it is for each correct value', () => { - const keys = Object.keys(JOB_FIELD_TYPES); + test('should returns all SUPPORTED_FIELD_TYPES labels exactly as it is for each correct value', () => { + const keys = Object.keys(SUPPORTED_FIELD_TYPES); const receivedLabels: Record = {}; const testStorage = jobTypeLabels; keys.forEach((key) => { - const constant = key as keyof typeof JOB_FIELD_TYPES; - receivedLabels[JOB_FIELD_TYPES[constant]] = getJobTypeLabel(JOB_FIELD_TYPES[constant]); + const constant = key as keyof typeof SUPPORTED_FIELD_TYPES; + receivedLabels[SUPPORTED_FIELD_TYPES[constant]] = getJobTypeLabel( + SUPPORTED_FIELD_TYPES[constant] + ); }); expect(receivedLabels).toEqual(testStorage); }); - test('should returns NULL as JOB_FIELD_TYPES does not contain such a keyword', () => { - expect(getJobTypeLabel('JOB_FIELD_TYPES')).toBe(null); + test('should returns NULL as SUPPORTED_FIELD_TYPES does not contain such a keyword', () => { + expect(getJobTypeLabel('SUPPORTED_FIELD_TYPES')).toBe(null); }); }); }); diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts b/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts index d9617ae61e2ec..5d1293f0a22b3 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts @@ -8,52 +8,70 @@ import { i18n } from '@kbn/i18n'; import { DataViewField } from '@kbn/data-views-plugin/public'; import { KBN_FIELD_TYPES } from '@kbn/data-plugin/common'; -import { JOB_FIELD_TYPES } from '../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../common/constants'; export const getJobTypeLabel = (type: string) => { return type in jobTypeLabels ? jobTypeLabels[type as keyof typeof jobTypeLabels] : null; }; export const jobTypeLabels = { - [JOB_FIELD_TYPES.BOOLEAN]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.booleanTypeLabel', { - defaultMessage: 'Boolean', - }), - [JOB_FIELD_TYPES.DATE]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.dateTypeLabel', { + [SUPPORTED_FIELD_TYPES.BOOLEAN]: i18n.translate( + 'xpack.dataVisualizer.fieldTypeIcon.booleanTypeLabel', + { + defaultMessage: 'Boolean', + } + ), + [SUPPORTED_FIELD_TYPES.DATE]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.dateTypeLabel', { defaultMessage: 'Date', }), - [JOB_FIELD_TYPES.GEO_POINT]: i18n.translate( + [SUPPORTED_FIELD_TYPES.GEO_POINT]: i18n.translate( 'xpack.dataVisualizer.fieldTypeIcon.geoPointTypeLabel', { defaultMessage: 'Geo point', } ), - [JOB_FIELD_TYPES.GEO_SHAPE]: i18n.translate( + [SUPPORTED_FIELD_TYPES.GEO_SHAPE]: i18n.translate( 'xpack.dataVisualizer.fieldTypeIcon.geoShapeTypeLabel', { defaultMessage: 'Geo shape', } ), - [JOB_FIELD_TYPES.IP]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.ipTypeLabel', { + [SUPPORTED_FIELD_TYPES.IP]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.ipTypeLabel', { defaultMessage: 'IP', }), - [JOB_FIELD_TYPES.KEYWORD]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.keywordTypeLabel', { - defaultMessage: 'Keyword', - }), - [JOB_FIELD_TYPES.NUMBER]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.numberTypeLabel', { - defaultMessage: 'Number', - }), - [JOB_FIELD_TYPES.HISTOGRAM]: i18n.translate( + [SUPPORTED_FIELD_TYPES.KEYWORD]: i18n.translate( + 'xpack.dataVisualizer.fieldTypeIcon.keywordTypeLabel', + { + defaultMessage: 'Keyword', + } + ), + [SUPPORTED_FIELD_TYPES.NUMBER]: i18n.translate( + 'xpack.dataVisualizer.fieldTypeIcon.numberTypeLabel', + { + defaultMessage: 'Number', + } + ), + [SUPPORTED_FIELD_TYPES.HISTOGRAM]: i18n.translate( 'xpack.dataVisualizer.fieldTypeIcon.histogramTypeLabel', { defaultMessage: 'Histogram', } ), - [JOB_FIELD_TYPES.TEXT]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.textTypeLabel', { + [SUPPORTED_FIELD_TYPES.TEXT]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.textTypeLabel', { defaultMessage: 'Text', }), - [JOB_FIELD_TYPES.UNKNOWN]: i18n.translate('xpack.dataVisualizer.fieldTypeIcon.unknownTypeLabel', { - defaultMessage: 'Unknown', - }), + [SUPPORTED_FIELD_TYPES.UNKNOWN]: i18n.translate( + 'xpack.dataVisualizer.fieldTypeIcon.unknownTypeLabel', + { + defaultMessage: 'Unknown', + } + ), + [SUPPORTED_FIELD_TYPES.VERSION]: i18n.translate( + 'xpack.dataVisualizer.fieldTypeIcon.versionTypeLabel', + { + defaultMessage: 'Version', + } + ), }; // convert kibana types to ML Job types @@ -62,30 +80,35 @@ export const jobTypeLabels = { export function kbnTypeToJobType(field: DataViewField) { // Return undefined if not one of the supported data visualizer field types. let type; + switch (field.type) { case KBN_FIELD_TYPES.STRING: - type = field.aggregatable ? JOB_FIELD_TYPES.KEYWORD : JOB_FIELD_TYPES.TEXT; + type = field.aggregatable ? SUPPORTED_FIELD_TYPES.KEYWORD : SUPPORTED_FIELD_TYPES.TEXT; + + if (field.esTypes?.includes(SUPPORTED_FIELD_TYPES.VERSION)) { + type = SUPPORTED_FIELD_TYPES.VERSION; + } break; case KBN_FIELD_TYPES.NUMBER: - type = JOB_FIELD_TYPES.NUMBER; + type = SUPPORTED_FIELD_TYPES.NUMBER; break; case KBN_FIELD_TYPES.DATE: - type = JOB_FIELD_TYPES.DATE; + type = SUPPORTED_FIELD_TYPES.DATE; break; case KBN_FIELD_TYPES.IP: - type = JOB_FIELD_TYPES.IP; + type = SUPPORTED_FIELD_TYPES.IP; break; case KBN_FIELD_TYPES.BOOLEAN: - type = JOB_FIELD_TYPES.BOOLEAN; + type = SUPPORTED_FIELD_TYPES.BOOLEAN; break; case KBN_FIELD_TYPES.GEO_POINT: - type = JOB_FIELD_TYPES.GEO_POINT; + type = SUPPORTED_FIELD_TYPES.GEO_POINT; break; case KBN_FIELD_TYPES.GEO_SHAPE: - type = JOB_FIELD_TYPES.GEO_SHAPE; + type = SUPPORTED_FIELD_TYPES.GEO_SHAPE; break; case KBN_FIELD_TYPES.HISTOGRAM: - type = JOB_FIELD_TYPES.HISTOGRAM; + type = SUPPORTED_FIELD_TYPES.HISTOGRAM; break; default: diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx index 0b4103687bbde..079804a47cd7b 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx @@ -399,7 +399,7 @@ export const IndexDataVisualizerView: FC = (dataVi
-

{currentDataView.title}

+

{currentDataView.getName()}

{ const fieldData = nonMetricFieldData.find((f) => f.fieldName === field.spec.name); - const nonMetricConfig: Partial = { ...(fieldData ? fieldData : {}), fieldFormat: currentDataView.getFormatterForField(field), diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_field_examples.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_field_examples.ts index 0e04665256e20..dfc68e6dac9ae 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_field_examples.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_field_examples.ts @@ -15,6 +15,8 @@ import type { ISearchStart, } from '@kbn/data-plugin/public'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import type { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { getUniqGeoOrStrExamples } from '../../../common/util/example_utils'; import { buildBaseFilterCriteria } from '../../../../../common/utils/query_utils'; import type { Field, @@ -90,20 +92,11 @@ export const fetchFieldsExamples = ( if (body.hits.total > 0) { const hits = body.hits.hits; - for (let i = 0; i < hits.length; i++) { - // Use lodash get() to support field names containing dots. - const doc: object[] | undefined = get(hits[i].fields, field.fieldName); - // the results from fields query is always an array - if (Array.isArray(doc) && doc.length > 0) { - const example = doc[0]; - if (example !== undefined && stats.examples.indexOf(example) === -1) { - stats.examples.push(example); - if (stats.examples.length === maxExamples) { - break; - } - } - } - } + const processedDocs = hits.map((hit: SearchHit) => { + const doc: object[] | undefined = get(hit.fields, field.fieldName); + return Array.isArray(doc) && doc.length > 0 ? doc[0] : doc; + }); + stats.examples = getUniqGeoOrStrExamples(processedDocs, maxExamples); } return stats; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_fields_stats.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_fields_stats.ts index 4dd0b3a7ba40a..a549e40704c0f 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_fields_stats.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/search_strategy/requests/get_fields_stats.ts @@ -11,7 +11,7 @@ import { ISearchStart } from '@kbn/data-plugin/public'; import type { FieldStatsCommonRequestParams } from '../../../../../common/types/field_stats'; import type { FieldStatsError } from '../../../../../common/types/field_stats'; import type { FieldStats } from '../../../../../common/types/field_stats'; -import { JOB_FIELD_TYPES } from '../../../../../common/constants'; +import { SUPPORTED_FIELD_TYPES } from '../../../../../common/constants'; import { fetchDateFieldsStats } from './get_date_field_stats'; import { fetchBooleanFieldsStats } from './get_boolean_field_stats'; import { fetchFieldsExamples } from './get_field_examples'; @@ -31,16 +31,17 @@ export const getFieldsStats = ( ): Observable | undefined => { const fieldType = fields[0].type; switch (fieldType) { - case JOB_FIELD_TYPES.NUMBER: + case SUPPORTED_FIELD_TYPES.NUMBER: return fetchNumericFieldsStats(dataSearch, params, fields, options); - case JOB_FIELD_TYPES.KEYWORD: - case JOB_FIELD_TYPES.IP: + case SUPPORTED_FIELD_TYPES.KEYWORD: + case SUPPORTED_FIELD_TYPES.IP: + case SUPPORTED_FIELD_TYPES.VERSION: return fetchStringFieldsStats(dataSearch, params, fields, options); - case JOB_FIELD_TYPES.DATE: + case SUPPORTED_FIELD_TYPES.DATE: return fetchDateFieldsStats(dataSearch, params, fields, options); - case JOB_FIELD_TYPES.BOOLEAN: + case SUPPORTED_FIELD_TYPES.BOOLEAN: return fetchBooleanFieldsStats(dataSearch, params, fields, options); - case JOB_FIELD_TYPES.TEXT: + case SUPPORTED_FIELD_TYPES.TEXT: return fetchFieldsExamples(dataSearch, params, fields, options); default: // Use an exists filter on the the field name to get diff --git a/x-pack/plugins/enterprise_search/server/types/connector.ts b/x-pack/plugins/enterprise_search/common/types/connectors.ts similarity index 61% rename from x-pack/plugins/enterprise_search/server/types/connector.ts rename to x-pack/plugins/enterprise_search/common/types/connectors.ts index 95e1e6876e4a8..bdeac44734286 100644 --- a/x-pack/plugins/enterprise_search/server/types/connector.ts +++ b/x-pack/plugins/enterprise_search/common/types/connectors.ts @@ -7,30 +7,44 @@ export interface KeyValuePair { label: string; - value: string | null; + value: string; } -export type ConnectorConfiguration = Record; +export type ConnectorConfiguration = Record; export interface ConnectorScheduling { enabled: boolean; interval: string; } +export enum ConnectorStatus { + CREATED = 'created', + NEEDS_CONFIGURATION = 'needs_configuration', + CONFIGURED = 'configured', + CONNECTED = 'connected', + ERROR = 'error', +} + +export enum SyncStatus { + IN_PROGRESS = 'in_progress', + COMPLETED = 'completed', + ERROR = 'error', +} export interface Connector { api_key_id: string | null; configuration: ConnectorConfiguration; - created_at: string | null; + id: string; index_name: string; last_seen: string | null; last_synced: string | null; - scheduling: ConnectorScheduling; + scheduling: { + enabled: boolean; + interval: string; // crontab syntax + }; service_type: string | null; - status: string | null; + status: ConnectorStatus; sync_error: string | null; sync_now: boolean; sync_status: string | null; } -export interface ConnectorWithId extends Connector { - id: string; -} +export type ConnectorDocument = Omit; diff --git a/x-pack/plugins/enterprise_search/common/types/indices.ts b/x-pack/plugins/enterprise_search/common/types/indices.ts index 485c2274a5f20..4b3007c36ec1d 100644 --- a/x-pack/plugins/enterprise_search/common/types/indices.ts +++ b/x-pack/plugins/enterprise_search/common/types/indices.ts @@ -14,9 +14,9 @@ import { export interface ElasticsearchIndex { health?: HealthStatus; - status?: IndicesStatsIndexMetadataState; + name: IndexName; - uuid?: Uuid; + status?: IndicesStatsIndexMetadataState; total: { docs: { count: number; @@ -26,4 +26,5 @@ export interface ElasticsearchIndex { size_in_bytes: string; }; }; + uuid?: Uuid; } diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router/state.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router/state.mock.ts index 0ce8673530b00..8939d7cd18f01 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router/state.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/react_router/state.mock.ts @@ -10,15 +10,6 @@ * Jest to accept its use within a jest.mock() */ -export const mockHistory = { - createHref: jest.fn(({ pathname }) => `/app/enterprise_search${pathname}`), - push: jest.fn(), - location: { - pathname: '/current-path', - }, - listen: jest.fn(() => jest.fn()), -} as any; - export const mockLocation = { key: 'someKey', pathname: '/current-path', @@ -26,3 +17,11 @@ export const mockLocation = { hash: '#hash', state: {}, }; + +export const mockHistory = { + createHref: jest.fn(({ pathname }) => `/app/enterprise_search${pathname}`), + push: jest.fn(), + location: mockLocation, + listen: jest.fn(() => jest.fn()), + basePath: '/app/enterprise_search', +} as any; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts index a37f7257f416e..3b3221a8dcb48 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts @@ -15,11 +15,10 @@ import { import { HttpLogic } from '../../../../shared/http'; import { KibanaLogic } from '../../../../shared/kibana'; import { ENGINE_CURATIONS_PATH } from '../../../routes'; -import { flattenDocument } from '../../../utils/results'; import { EngineLogic, generateEnginePath } from '../../engine'; import { DELETE_SUCCESS_MESSAGE } from '../constants'; -import { Curation, CurationResult } from '../types'; +import { Curation } from '../types'; import { addDocument, removeDocument } from '../utils'; type CurationPageTabs = 'promoted' | 'history' | 'hidden'; @@ -236,12 +235,8 @@ export const CurationLogic = kea flattenDocument(x) as CurationResult), - promoted: response.promoted.map((x) => flattenDocument(x) as CurationResult), - }; - actions.onCurationLoad(payload); + + actions.onCurationLoad(response); } catch (e) { const { navigateToUrl } = KibanaLogic.values; @@ -269,12 +264,8 @@ export const CurationLogic = kea flattenDocument(x) as CurationResult), - promoted: response.promoted.map((x) => flattenDocument(x) as CurationResult), - }; - actions.onCurationLoad(payload); + + actions.onCurationLoad(response); } catch (e) { flashAPIErrors(e); actions.onCurationError(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/utils.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/utils.test.ts index 7bc05f34511a0..2aabb2760695e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/utils.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/utils.test.ts @@ -21,15 +21,12 @@ describe('convertToResultFormat', () => { }, id: { raw: 'some-id', - snippet: null, }, someField: { raw: 'some flat string', - snippet: null, }, anotherField: { raw: '123456', - snippet: null, }, }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/utils.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/utils.ts index 5c56eb934b150..9f9340fe46537 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/utils.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/results/utils.ts @@ -28,25 +28,30 @@ const mergeMetas = (partialMeta: ResultMeta, secondPartialMeta: ResultMeta): Res }; }; -export const convertToResultFormat = (document: CurationResult): SearchResult => { - const result = {} as SearchResult; +const isNestedObject = (value: unknown): boolean => { + if (Array.isArray(value)) { + return value.reduce( + (isNested: boolean, currentValue) => isNested || isNestedObject(currentValue), + false + ); + } + + return value === null || typeof value === 'object'; +}; +export const convertToResultFormat = (document: CurationResult): SearchResult => { // Convert `key: 'value'` into `key: { raw: 'value' }` - Object.entries(document).forEach(([key, value]) => { - // don't convert _meta if exists - if (key === '_meta') { - result[key] = value as ResultMeta; - } else { - result[key] = { - raw: value, - snippet: null, // Don't try to provide a snippet, we can't really guesstimate it - }; - } - }); + const result = Object.entries(document).reduce((acc, [key, value]) => { + return { + ...acc, + [key]: + isNestedObject(value) || Object.prototype.hasOwnProperty.call(value, 'raw') + ? value + : { raw: value }, + }; + }, {} as SearchResult); - // Add the _meta obj needed by Result - const convertedMetaObj = convertIdToMeta(document.id); - result._meta = mergeMetas(result._meta, convertedMetaObj); + result._meta = mergeMetas(result._meta, convertIdToMeta(document.id)); return result; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts index 73aefbdfd205d..9d4497e5d72a8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/types.ts @@ -8,7 +8,7 @@ import type { SearchResult } from '@elastic/search-ui'; import { Meta } from '../../../../../common/types'; -import { ResultMeta } from '../result/types'; +import { ResultMeta, SimpleFieldValue } from '../result/types'; export interface CurationSuggestion { query: string; @@ -47,5 +47,9 @@ export interface CurationResult { // TODO: Consider updating our internal API to return more standard Result data in the future id: string; _meta?: ResultMeta; - [key: string]: string | string[] | ResultMeta | unknown | undefined; + [key: string]: SimpleFieldValue | ResultMeta | CurationResultNestedFieldValue | undefined; } + +type CurationResultNestedFieldValue = + | { [key: string]: SimpleFieldValue | CurationResultNestedFieldValue } + | CurationResultNestedFieldValue[]; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx index 604d2930a4b5d..f20684dc1a107 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion.test.tsx @@ -90,11 +90,9 @@ describe('CurationSuggestion', () => { { id: { raw: '1', - snippet: null, }, foo: { raw: 'foo', - snippet: null, }, _meta: { id: '1', @@ -110,11 +108,9 @@ describe('CurationSuggestion', () => { { id: { raw: '4', - snippet: null, }, foo: { raw: 'foo', - snippet: null, }, _meta: { id: '4', diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/nav.tsx index 793a36f48fe82..20bbfe38e5f39 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/layout/nav.tsx @@ -30,7 +30,6 @@ export const useAppSearchNav = () => { name: ENGINES_TITLE, ...generateNavLink({ to: ENGINES_PATH, - isRoot: true, shouldShowActiveForSubroutes: true, items: useEngineNav(), }), diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_form.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_form.test.tsx index d4052f23cfca4..6c6a4a7c05667 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_form.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_form.test.tsx @@ -25,8 +25,8 @@ describe('RelevanceTuningForm', () => { filteredSchemaFields: ['foo', 'bar'], filteredSchemaFieldsWithConflicts: [], schema: { - foo: 'text', - bar: 'number', + foo: { type: 'text' }, + bar: { type: 'number' }, }, searchSettings: { boosts: { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_form.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_form.tsx index 39200a699b3f7..786fb4bc778d2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_form.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_form.tsx @@ -81,7 +81,7 @@ export const RelevanceTuningForm: React.FC = () => { buttonContent={ @@ -90,7 +90,7 @@ export const RelevanceTuningForm: React.FC = () => { > diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts index 82326e9494c94..a512b87ececc8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.test.ts @@ -942,7 +942,7 @@ describe('RelevanceTuningLogic', () => { it('will parse the provided provided value and set the center to that parsed value', () => { mount({ schema: { - foo: 'number', + foo: { type: 'number', capabilities: { boost: true } }, }, searchSettings: searchSettingsWithBoost({ factor: 1, @@ -1046,7 +1046,7 @@ describe('RelevanceTuningLogic', () => { // consider a tunable field. mount({ schema: { - id: 'foo', + id: { type: 'text', capabilities: {} }, }, }); expect(RelevanceTuningLogic.values.engineHasSchemaFields).toEqual(false); @@ -1055,8 +1055,8 @@ describe('RelevanceTuningLogic', () => { it('should return true otherwise', () => { mount({ schema: { - id: 'foo', - bar: 'bar', + id: { type: 'text', capabilities: {} }, + text_field: { type: 'text', capabilities: { fulltext: true } }, }, }); expect(RelevanceTuningLogic.values.engineHasSchemaFields).toEqual(true); @@ -1067,11 +1067,39 @@ describe('RelevanceTuningLogic', () => { it('should return the list of field names from the schema', () => { mount({ schema: { - id: 'foo', - bar: 'bar', + fulltext_only_field: { + type: 'text', + capabilities: { + fulltext: true, + }, + }, + boost_only_field: { + type: 'text', + capabilities: { + boost: true, + }, + }, + fulltext_and_boost_field: { + type: 'text', + capabilities: { + fulltext: true, + boost: true, + }, + }, + ignored_field: { + type: 'text', + capabilities: { + fulltext: false, + boost: false, + }, + }, }, }); - expect(RelevanceTuningLogic.values.schemaFields).toEqual(['id', 'bar']); + expect(RelevanceTuningLogic.values.schemaFields).toEqual([ + 'fulltext_only_field', + 'boost_only_field', + 'fulltext_and_boost_field', + ]); }); }); @@ -1092,15 +1120,40 @@ describe('RelevanceTuningLogic', () => { describe('filteredSchemaFields', () => { it('should return a list of schema field names that contain the text from filterInputValue ', () => { mount({ - filterInputValue: 'ba', + filterInputValue: 'fu', schema: { - id: 'string', - foo: 'string', - bar: 'string', - baz: 'string', + fulltext_only_field: { + type: 'text', + capabilities: { + fulltext: true, + }, + }, + boost_only_field: { + type: 'text', + capabilities: { + boost: true, + }, + }, + fulltext_and_boost_field: { + type: 'text', + capabilities: { + fulltext: true, + boost: true, + }, + }, + ignored_field: { + type: 'text', + capabilities: { + fulltext: false, + boost: false, + }, + }, }, }); - expect(RelevanceTuningLogic.values.filteredSchemaFields).toEqual(['bar', 'baz']); + expect(RelevanceTuningLogic.values.filteredSchemaFields).toEqual([ + 'fulltext_only_field', + 'fulltext_and_boost_field', + ]); }); }); @@ -1108,12 +1161,7 @@ describe('RelevanceTuningLogic', () => { it('should return a list of schema field names that contain the text from filterInputValue, and if that field has a schema conflict', () => { mount({ filterInputValue: 'ba', - schema: { - id: 'string', - foo: 'string', - bar: 'string', - baz: 'string', - }, + schema: {}, schemaConflicts: { bar: { text: ['source_engine_1'], diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts index f1e16e04d909a..76411a427e791 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_logic.ts @@ -16,7 +16,7 @@ import { clearFlashMessages, } from '../../../shared/flash_messages'; import { HttpLogic } from '../../../shared/http'; -import { Schema, SchemaConflicts } from '../../../shared/schema/types'; +import { AdvancedSchema, SchemaConflicts } from '../../../shared/schema/types'; import { EngineLogic } from '../engine'; @@ -39,7 +39,7 @@ import { interface RelevanceTuningProps { searchSettings: SearchSettings; - schema: Schema; + schema: AdvancedSchema; schemaConflicts?: SchemaConflicts; } @@ -94,7 +94,7 @@ interface RelevanceTuningActions { interface RelevanceTuningValues { searchSettings: SearchSettings; - schema: Schema; + schema: AdvancedSchema; schemaFields: string[]; schemaFieldsWithConflicts: string[]; filteredSchemaFields: string[]; @@ -221,7 +221,18 @@ export const RelevanceTuningLogic = kea< ], }), selectors: ({ selectors }) => ({ - schemaFields: [() => [selectors.schema], (schema: Schema) => Object.keys(schema)], + schemaFields: [ + () => [selectors.schema], + (schema: AdvancedSchema) => + Object.entries(schema).reduce( + (fields: string[], [fieldName, { capabilities: fieldCapabilities }]) => { + return fieldCapabilities.fulltext || fieldCapabilities.boost + ? [...fields, fieldName] + : fields; + }, + [] + ), + ], schemaFieldsWithConflicts: [ () => [selectors.schemaConflicts], (schemaConflicts: SchemaConflicts) => Object.keys(schemaConflicts), @@ -237,8 +248,8 @@ export const RelevanceTuningLogic = kea< filterIfTerm(schemaFieldsWithConflicts, filterInputValue), ], engineHasSchemaFields: [ - () => [selectors.schema], - (schema: Schema): boolean => Object.keys(schema).length >= 2, + () => [selectors.schemaFields], + (schemaFields: string[]): boolean => schemaFields.length > 0, ], isPrecisionTuningEnabled: [ () => [selectors.searchSettings], @@ -453,7 +464,7 @@ export const RelevanceTuningLogic = kea< const { searchSettings } = values; const { boosts } = searchSettings; const updatedBoosts = cloneDeep(boosts[name]); - const fieldType = values.schema[name]; + const fieldType = values.schema[name].type; updatedBoosts[boostIndex].center = parseBoostCenter(fieldType, value); actions.setSearchSettings({ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx index 0c78cc672a609..155b831315e0d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.tsx @@ -16,11 +16,11 @@ import type { SearchResult } from '@elastic/search-ui'; import { i18n } from '@kbn/i18n'; import { KibanaLogic } from '../../../shared/kibana'; -import { Schema } from '../../../shared/schema/types'; +import { AdvancedSchema, Schema } from '../../../shared/schema/types'; import { ENGINE_DOCUMENT_DETAIL_PATH } from '../../routes'; import { generateEncodedPath } from '../../utils/encode_path_params'; -import { flattenDocument } from '../../utils/results'; +import { formatResultWithoutMeta } from '../../utils/results'; import { ResultField } from './result_field'; import { ResultHeader } from './result_header'; @@ -32,7 +32,7 @@ interface Props { showScore?: boolean; resultPosition?: number; shouldLinkToDetailPage?: boolean; - schemaForTypeHighlights?: Schema; + schemaForTypeHighlights?: Schema | AdvancedSchema; actions?: ResultAction[]; dragHandleProps?: DraggableProvidedDragHandleProps; showClick?: boolean; @@ -57,12 +57,24 @@ export const Result: React.FC = ({ const META = '_meta'; const resultMeta = result[META]; const resultFields = useMemo( - () => Object.entries(flattenDocument(result)).filter(([key]) => key !== META && key !== ID), + () => Object.entries(formatResultWithoutMeta(result)).filter(([key]) => key !== ID), [result] ); const numResults = resultFields.length; + const isAdvancedSchema = (schema: Schema | AdvancedSchema): schema is AdvancedSchema => { + return ( + schema && + Object.values(schema).reduce((isAdvanced, schemaField) => { + return isAdvanced && typeof schemaField !== 'string'; + }, true) + ); + }; const typeForField = (fieldName: string) => { - if (schemaForTypeHighlights) return schemaForTypeHighlights[fieldName]; + if (schemaForTypeHighlights) { + return isAdvancedSchema(schemaForTypeHighlights) + ? schemaForTypeHighlights[fieldName].type + : schemaForTypeHighlights[fieldName]; + } }; const documentLink = shouldLinkToDetailPage diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field_value.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field_value.tsx index 76bac7cf096e8..30730dbadc578 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field_value.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field_value.tsx @@ -9,7 +9,9 @@ import React from 'react'; import classNames from 'classnames'; -import { FieldType, Raw, Snippet } from './types'; +import { SchemaType } from '../../../shared/schema/types'; + +import { FieldType, Raw, SimpleFieldValue, Snippet } from './types'; import './result_field_value.scss'; @@ -18,7 +20,27 @@ const isNotNumeric = (raw: string | number): boolean => { return isNaN(parseFloat(raw)); }; -const getRawArrayDisplay = (rawArray: Array): string => { +const isScalarValue = (_: Raw, type?: FieldType): _ is SimpleFieldValue => { + return type !== SchemaType.Nested; +}; + +const getRawDisplay = (raw?: Raw, type?: FieldType): string | null => { + if (!raw) { + return null; + } + + if (!isScalarValue(raw, type)) { + return JSON.stringify(raw); + } + + if (Array.isArray(raw)) { + return getRawArrayDisplay(raw); + } + + return raw.toString(); +}; + +const getRawArrayDisplay = (rawArray: string[] | number[]): string => { return `[${rawArray.map((raw) => (isNotNumeric(raw) ? `"${raw}"` : raw)).join(', ')}]`; }; @@ -56,7 +78,7 @@ export const ResultFieldValue: React.FC = ({ snippet, raw, type, classNam */ dangerouslySetInnerHTML={snippet ? { __html: parseHighlights(snippet) } : undefined} // eslint-disable-line react/no-danger > - {!!snippet ? null : Array.isArray(raw) ? getRawArrayDisplay(raw) : raw} + {!!snippet ? null : getRawDisplay(raw, type)}
); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts index 9ffc535edaca2..45e9996b1afa2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/types.ts @@ -11,7 +11,11 @@ import { InternalSchemaType, SchemaType } from '../../../shared/schema/types'; export type FieldType = InternalSchemaType | SchemaType; -export type Raw = string | string[] | number | number[]; +export type NestedFieldValue = + | { [fieldName: string]: SimpleFieldValue | NestedFieldValue } + | NestedFieldValue[]; +export type SimpleFieldValue = string | string[] | number | number[]; +export type Raw = SimpleFieldValue | NestedFieldValue; export type Snippet = string; export interface FieldValue { raw?: Raw; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts index 4097e693aff11..6b641de15da46 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search/search_logic.ts @@ -12,7 +12,7 @@ import type { SearchResult } from '@elastic/search-ui'; import { flashAPIErrors } from '../../../shared/flash_messages'; import { HttpLogic } from '../../../shared/http'; -import { flattenDocument } from '../../utils/results'; +import { formatResult } from '../../utils/results'; import { EngineLogic } from '../engine'; interface SearchValues { @@ -50,7 +50,7 @@ export const SearchLogic = kea>({ searchResults: [ [], { - onSearch: (_, { results }) => results.map((res) => flattenDocument(res) as SearchResult), + onSearch: (_, { results }) => results.map((res) => formatResult(res) as SearchResult), }, ], }), diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.test.ts index c330ce62b474a..b020a4150d5fc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.test.ts @@ -4,57 +4,93 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { SearchResult } from '@elastic/search-ui'; -import { flattenDocument, flattenDocumentField } from '.'; +import { formatResult } from '.'; -describe('flattenDocumentField', () => { - it('flattens field if raw key is absent', () => { - expect(flattenDocumentField('address', { country: { raw: 'United States' } })).toEqual([ - ['address.country', { raw: 'United States' }], - ]); - }); - it('preserves field if raw key is present', () => { - expect(flattenDocumentField('country', { raw: 'United States' })).toEqual([ - ['country', { raw: 'United States' }], - ]); - }); - it('can flatten multiple levels', () => { +describe('formatResult', () => { + it('format the result', () => { const data = { - name: { raw: 'Bubba Gump' }, - address: { - street: { raw: 'South St' }, - country: { - code: { raw: 'US' }, - name: { raw: 'United States' }, - }, - }, + id: { raw: 'doc-id' }, + text_field: { raw: 'text value' }, + numeric_field: { raw: 21 }, + multivalued_field: { raw: ['value_1', 'value_2'] }, + 'simple_object.flattened': { raw: ['value_1', 'value_2'] }, + raw: { raw: 'raw_value' }, + snippet: { snippet: 'snipet_value' }, }; - const expected = [ - ['customer.name', { raw: 'Bubba Gump' }], - ['customer.address.street', { raw: 'South St' }], - ['customer.address.country.code', { raw: 'US' }], - ['customer.address.country.name', { raw: 'United States' }], - ]; - expect(flattenDocumentField('customer', data)).toEqual(expected); + + expect(formatResult(data)).toEqual(data); }); -}); -describe('flattenDocument', () => { - it('flattens all fields without raw key', () => { - const result: SearchResult = { - id: { raw: '123' }, - _meta: { engine: 'Test', id: '1' }, - title: { raw: 'Getty Museum' }, - address: { city: { raw: 'Los Angeles' }, state: { raw: 'California' } }, - }; - const expected: SearchResult = { - id: { raw: '123' }, - _meta: { engine: 'Test', id: '1' }, - title: { raw: 'Getty Museum' }, - 'address.city': { raw: 'Los Angeles' }, - 'address.state': { raw: 'California' }, + describe('with nested objects', () => { + describe('single value field', () => { + it('transform nested field values', () => { + expect( + formatResult({ + id: { raw: 'doc-id' }, + nested_object: { + subfield_1: { raw: ['value 1', 'value 2'] }, + subfield_2: { raw: 'value 3' }, + }, + }) + ).toEqual({ + id: { raw: 'doc-id' }, + nested_object: { + raw: { + subfield_1: ['value 1', 'value 2'], + subfield_2: 'value 3', + }, + }, + }); + }); + }); + + describe('multi-valued field', () => { + it('transform nested field values', () => { + expect( + formatResult({ + id: { raw: 'doc-id' }, + nested_object: [ + { + subfield_1: { raw: ['value 1', 'value 2'] }, + subfield_2: { raw: 'value 3' }, + raw: { raw: 'raw_value' }, + snippet: { raw: 'snippert_value' }, + }, + { + subfield_1: { raw: 'value 4' }, + raw: { raw: ['raw_value'] }, + snippet: { raw: ['snippert_value'] }, + }, + ], + }) + ).toEqual({ + id: { raw: 'doc-id' }, + nested_object: { + raw: [ + { + subfield_1: ['value 1', 'value 2'], + subfield_2: 'value 3', + raw: 'raw_value', + snippet: 'snippert_value', + }, + { + subfield_1: 'value 4', + raw: ['raw_value'], + snippet: ['snippert_value'], + }, + ], + }, + }); + }); + }); + }); + + it('does not consider _meta field as a nested field', () => { + const data = { + id: { raw: 'doc-id' }, + _meta: { id: '1', _score: 12, engine: 'foo-engine' }, }; - expect(flattenDocument(result)).toEqual(expected); + expect(formatResult(data)).toEqual(data); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.ts index 945dd1418801a..673f577c0033e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/utils/results/index.ts @@ -5,70 +5,109 @@ * 2.0. */ -/* This method flattens fields in documents returned from the ent-search backend. - * If a field in the document contains "raw" key, it's already flat. - * If it doesn't, we want to pull properties from it, and move them to the top level. - * This field is already flat: - * 'country', { raw: 'United States' } - * This field is not flat: - * 'address', { - * country: { raw: 'United States' }, - * city: { raw: 'Los Angeles' } - * } - * It will be transformed into: - * [ - * ['address.country', { raw: 'United States' }], - * ['address.city', { raw: 'Los Angeles' }] - * ] - */ -export const flattenDocumentField = ( - fieldName: string, - fieldValue: object -): Array<[string, object]> => { - const flattened: Array<[string, object]> = []; - - if (typeof fieldValue === 'object' && !fieldValue.hasOwnProperty('raw')) { - for (const [propName, value] of Object.entries(fieldValue)) { - flattenDocumentField(fieldName + '.' + propName, value).map(([flatKey, flatVal]) => { - flattened.push([flatKey, flatVal]); - }); - } - } else { - flattened.push([fieldName, fieldValue]); - } +import { + FieldValue, + NestedFieldValue, + ResultMeta, + SimpleFieldValue, + Snippet, +} from '../../components/result/types'; - return flattened; -}; - -/* This method flattens documents returned from the ent-search backend. - * Example document: - * { - * id: { raw: '123' }, - * _meta: { engine: 'Test', id: '1' }, - * title: { raw: 'Getty Museum' }, - * address: { city: { raw: 'Los Angeles' }, state: { raw: 'California' } }, - * } - * Will be transformed to: - * { - * id: { raw: '123' }, - * _meta: { engine: 'Test', id: '1' }, - * title: { raw: 'Getty Museum' }, - * 'address.city': { raw: 'Los Angeles' }, - * 'address.state': { raw: 'California' }, - * } - */ -export const flattenDocument = (result: object): object => { - const flattened: { [index: string]: object } = {}; - - for (const [key, value] of Object.entries(result)) { - if (key === 'id' || key === '_meta') { - flattened[key] = value; - } else { - for (const [flatName, flatValue] of flattenDocumentField(key, value)) { - flattened[flatName] = flatValue; +interface SearchApiWrappedFieldValue { + raw?: SimpleFieldValue; + snippet?: Snippet; +} +type SearchApiNestedFieldValue = + | { [key: string]: SearchApiNestedFieldValue | SearchApiWrappedFieldValue } + | SearchApiNestedFieldValue[]; +type SearchApiFieldValue = ResultMeta | SearchApiWrappedFieldValue | SearchApiNestedFieldValue; + +function isResultMeta(fieldName: string, _: SearchApiFieldValue): _ is ResultMeta { + return fieldName === '_meta'; +} + +function isFieldValueWrapper( + fieldValue: SearchApiFieldValue +): fieldValue is SearchApiWrappedFieldValue { + return ( + fieldValue && + Object.entries(fieldValue).reduce((isValueWrapper: boolean, [k, v]) => { + if (k !== 'raw' && k !== 'snippet') { + return false; } - } + + if (v === null) { + return isValueWrapper; + } + + return (Array.isArray(v) ? v : [v]).reduce((isScalar, currentValue) => { + return isScalar && currentValue !== null && typeof currentValue !== 'object'; + }, isValueWrapper); + }, true) + ); +} + +function isNestedFieldValue( + fieldValue: SearchApiFieldValue +): fieldValue is SearchApiNestedFieldValue { + if (Array.isArray(fieldValue)) { + return fieldValue.reduce( + (isNested: boolean, current) => isNested || isNestedFieldValue(current), + false + ); + } + + return fieldValue != null && typeof fieldValue === 'object' && !isFieldValueWrapper(fieldValue); +} + +function formatNestedFieldValue( + fieldValue: SearchApiNestedFieldValue | SearchApiWrappedFieldValue +): NestedFieldValue { + if (Array.isArray(fieldValue)) { + return fieldValue.map(formatNestedFieldValue); + } + + if (fieldValue !== null && typeof fieldValue === 'object') { + return Object.entries(fieldValue).reduce( + (formattedFieldValue, [nestedFieldName, currentValue]) => { + return { + ...formattedFieldValue, + [nestedFieldName]: isFieldValueWrapper(currentValue) + ? currentValue.raw + : formatNestedFieldValue(currentValue), + }; + }, + {} + ); } - return flattened; -}; + return fieldValue; +} + +export function formatResult( + result: Record +): Record { + return Object.entries(result).reduce((acc, [fieldName, fieldValue]) => { + if (!isResultMeta(fieldName, fieldValue) && isNestedFieldValue(fieldValue)) { + return { ...acc, [fieldName]: { raw: formatNestedFieldValue(fieldValue) } }; + } + + return { ...acc, [fieldName]: fieldValue }; + }, {}); +} + +export function formatResultWithoutMeta( + result: Record +): Record { + return Object.entries(result).reduce((acc, [fieldName, fieldValue]) => { + if (isResultMeta(fieldName, fieldValue)) { + return { ...acc }; + } + + if (isNestedFieldValue(fieldValue)) { + return { ...acc, [fieldName]: { raw: formatNestedFieldValue(fieldValue) } }; + } + + return { ...acc, [fieldName]: fieldValue }; + }, {}); +} diff --git a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/elasticsearch_guide/elasticsearch_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/elasticsearch_guide/elasticsearch_guide.tsx index cc5c3c90c4ac8..7dba7836e8599 100644 --- a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/elasticsearch_guide/elasticsearch_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/elasticsearch_guide/elasticsearch_guide.tsx @@ -10,7 +10,6 @@ import React, { useEffect, useState } from 'react'; import queryString from 'query-string'; import { - EuiPageTemplate, EuiText, EuiFlexGroup, EuiFlexItem, @@ -26,9 +25,9 @@ import { i18n } from '@kbn/i18n'; import { docLinks } from '../../../shared/doc_links'; import { ElasticsearchResources } from '../../../shared/elasticsearch_resources'; import { SetElasticsearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; - import { ElasticsearchClientInstructions } from '../elasticsearch_client_instructions'; import { ElasticsearchCloudId } from '../elasticsearch_cloud_id'; +import { EnterpriseSearchElasticsearchPageTemplate } from '../layout'; // Replace FormattedMessage with i18n strings @@ -61,7 +60,7 @@ export const ElasticsearchGuide: React.FC = () => { }, []); return ( - + {/* maxWidth is needed to prevent code blocks with long unbreakable strings (Kibana PR Cloud ID) from stretching the column */} @@ -193,6 +192,6 @@ export const ElasticsearchGuide: React.FC = () => { - + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/index.ts b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/index.ts index 3eedc5e5de879..d373c68d1ec41 100644 --- a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/index.ts @@ -5,5 +5,4 @@ * 2.0. */ -export { useEnterpriseSearchElasticsearchNav } from './nav'; export { EnterpriseSearchElasticsearchPageTemplate } from './page_template'; diff --git a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/nav.test.tsx deleted file mode 100644 index 598f3005fe5dc..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/nav.test.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -jest.mock('../../../shared/layout', () => ({ - generateNavLink: jest.fn(({ to, items }) => ({ href: to, items })), -})); - -import { useEnterpriseSearchElasticsearchNav } from '.'; - -describe('useEnterpriseSearchElasticsearchNav', () => { - it('returns an array of top-level Enterprise Search nav items', () => { - expect(useEnterpriseSearchElasticsearchNav()).toEqual([ - { - id: 'es_overview', - name: 'Overview', - emphasize: true, - isSelected: true, - href: '/app/enterprise_search/overview', - }, - { - id: 'content', - name: 'Content', - emphasize: true, - href: '/app/enterprise_search/content', - }, - { - id: 'elasticsearch', - name: 'Elasticsearch', - emphasize: true, - href: '/app/enterprise_search/elasticsearch', - }, - { - id: 'app_search', - name: 'App Search', - emphasize: true, - href: '/app/enterprise_search/app_search', - }, - { - id: 'workplace_search', - name: 'Workplace Search', - emphasize: true, - href: '/app/enterprise_search/workplace_search', - }, - ]); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/nav.tsx deleted file mode 100644 index 08c67d1408c6f..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/nav.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiSideNavItemType } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { - APP_SEARCH_PLUGIN, - ELASTICSEARCH_PLUGIN, - ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, - ENTERPRISE_SEARCH_CONTENT_PLUGIN, - WORKPLACE_SEARCH_PLUGIN, -} from '../../../../../common/constants'; -import { generateNavLink } from '../../../shared/layout'; - -export const useEnterpriseSearchElasticsearchNav = () => { - const navItems: Array> = [ - { - id: 'es_overview', - isSelected: true, - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.enterpriseSearchOverviewTitle', { - defaultMessage: 'Overview', - }), - href: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, - }, - { - id: 'content', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.contentTitle', { - defaultMessage: 'Content', - }), - ...generateNavLink({ - to: ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - { - id: 'elasticsearch', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.elasticsearch.nav.contentTitle', { - defaultMessage: 'Elasticsearch', - }), - ...generateNavLink({ - to: ELASTICSEARCH_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - { - id: 'app_search', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.appSearchTitle', { - defaultMessage: 'App Search', - }), - ...generateNavLink({ - to: APP_SEARCH_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - { - id: 'workplace_search', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.workplaceSearchTitle', { - defaultMessage: 'Workplace Search', - }), - ...generateNavLink({ - to: WORKPLACE_SEARCH_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - ]; - - return navItems; -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/page_template.test.tsx b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/page_template.test.tsx index 25551715bc444..a6885bb8adc9c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/page_template.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/page_template.test.tsx @@ -5,8 +5,8 @@ * 2.0. */ -jest.mock('./nav', () => ({ - useEnterpriseSearchElasticsearchNav: () => [], +jest.mock('../../../shared/layout/nav', () => ({ + useEnterpriseSearchNav: () => [], })); import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/page_template.tsx index bbcb442bd4f6b..f854246a9f9a7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/page_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/elasticsearch/components/layout/page_template.tsx @@ -10,10 +10,9 @@ import React from 'react'; import { ELASTICSEARCH_PLUGIN } from '../../../../../common/constants'; import { SetElasticsearchChrome } from '../../../shared/kibana_chrome'; import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; +import { useEnterpriseSearchNav } from '../../../shared/layout'; import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry'; -import { useEnterpriseSearchElasticsearchNav } from './nav'; - export const EnterpriseSearchElasticsearchPageTemplate: React.FC = ({ children, pageChrome, @@ -25,7 +24,7 @@ export const EnterpriseSearchElasticsearchPageTemplate: React.FC} > diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector_package/update_connector_configuration_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector_package/update_connector_configuration_api_logic.ts index 91c6495f3cdfb..49373a45eb99c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector_package/update_connector_configuration_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector_package/update_connector_configuration_api_logic.ts @@ -5,11 +5,10 @@ * 2.0. */ +import { ConnectorConfiguration } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; -import { ConnectorConfiguration } from '../index/fetch_index_api_logic'; - export interface PostConnectorConfigurationArgs { configuration: ConnectorConfiguration; indexId: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector_package/update_connector_scheduling_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector_package/update_connector_scheduling_api_logic.ts index 47679ee1caa0e..eebbd2b2bedf4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector_package/update_connector_scheduling_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector_package/update_connector_scheduling_api_logic.ts @@ -5,9 +5,9 @@ * 2.0. */ +import { ConnectorScheduling } from '../../../../../common/types/connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; -import { ConnectorScheduling } from '../index/fetch_index_api_logic'; export interface UpdateConnectorSchedulingArgs { connectorId: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/create_crawler_index_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/create_crawler_index_api_logic.ts index 81194357faea1..93532514703f1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/create_crawler_index_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/create_crawler_index_api_logic.ts @@ -7,15 +7,16 @@ import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; +import { LanguageForOptimization } from '../../components/new_index/types'; export interface CreateCrawlerIndexArgs { indexName: string; - language: string; + language: LanguageForOptimization; } interface CreateCrawlerIndexRequest { index_name: string; - language: string; + language: LanguageForOptimization; } export interface CreateCrawlerIndexResponse { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/fetch_index_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/fetch_index_api_logic.ts index adfd99a8a2d24..87ab8ecc700ba 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/fetch_index_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/fetch_index_api_logic.ts @@ -7,57 +7,7 @@ import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; - -export interface KeyValuePair { - label: string; - value: string; -} - -export type ConnectorConfiguration = Record; -export interface ConnectorScheduling { - enabled: boolean; - interval: string; -} - -export interface Connector { - api_key_id: string | null; - configuration: ConnectorConfiguration; - created_at: string | null; - id: string; - index_name: string; - last_seen: string | null; - last_synced: string | null; - scheduling: { - enabled: boolean; - interval: string; // crontab syntax - }; - service_type: string | null; - status: string; - sync_error: string | null; - sync_now: boolean; - sync_status: string | null; -} - -export interface Crawler { - domains: []; -} - -export interface IndexData { - connector?: Connector; - crawler?: Crawler; - index: { - aliases: string[]; - health: string; - name: string; - total: { - docs: { - count: number; - deleted: number; - }; - }; - uuid: string; - }; -} +import { IndexData } from '../../types'; export const fetchIndex = async ({ indexName }: { indexName: string }) => { const route = `/internal/enterprise_search/indices/${indexName}`; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/index.ts index 4ab6f30869363..d7865fe340bf5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/index.ts @@ -5,5 +5,4 @@ * 2.0. */ -export { useEnterpriseSearchContentNav } from './nav'; export { EnterpriseSearchContentPageTemplate } from './page_template'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/nav.test.tsx deleted file mode 100644 index 9b3375f1d168f..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/nav.test.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -jest.mock('../../../shared/layout', () => ({ - generateNavLink: jest.fn(({ to, items }) => ({ href: to, items })), -})); -jest.mock('../search_index/index_nav', () => ({ - useSearchIndicesNav: () => [], -})); - -import { useEnterpriseSearchContentNav } from '.'; - -describe('useEnterpriseSearchContentNav', () => { - it('returns an array of top-level Enterprise Search nav items', () => { - expect(useEnterpriseSearchContentNav()).toEqual([ - { - id: 'es_overview', - name: 'Overview', - emphasize: true, - items: undefined, - href: '/app/enterprise_search/overview', - }, - { - id: 'content', - name: 'Content', - emphasize: true, - href: '/', - items: [ - { - href: '/search_indices', - id: 'search_indices', - items: [], - name: 'Search indices', - }, - { - href: '/settings', - id: 'settings', - items: undefined, - name: 'Settings', - }, - ], - }, - { - id: 'app_search', - name: 'App Search', - emphasize: true, - items: undefined, - href: '/app/enterprise_search/app_search', - }, - { - id: 'workplace_search', - name: 'Workplace Search', - emphasize: true, - items: undefined, - href: '/app/enterprise_search/workplace_search', - }, - ]); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/nav.tsx deleted file mode 100644 index af3f5dd9c48e8..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/nav.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiSideNavItemType } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { - APP_SEARCH_PLUGIN, - ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, - WORKPLACE_SEARCH_PLUGIN, -} from '../../../../../common/constants'; -import { generateNavLink } from '../../../shared/layout'; - -import { ROOT_PATH, SEARCH_INDICES_PATH, SETTINGS_PATH } from '../../routes'; - -import { useSearchIndicesNav } from '../search_index/index_nav'; - -export const useEnterpriseSearchContentNav = () => { - const navItems: Array> = [ - { - id: 'es_overview', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.enterpriseSearchOverviewTitle', { - defaultMessage: 'Overview', - }), - ...generateNavLink({ - to: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - { - id: 'content', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.contentTitle', { - defaultMessage: 'Content', - }), - ...generateNavLink({ - to: ROOT_PATH, - isRoot: true, - shouldShowActiveForSubroutes: false, - items: [ - { - id: 'search_indices', - name: i18n.translate('xpack.enterpriseSearch.content.nav.searchIndicesTitle', { - defaultMessage: 'Search indices', - }), - ...generateNavLink({ - to: SEARCH_INDICES_PATH, - isRoot: true, - shouldShowActiveForSubroutes: true, - items: useSearchIndicesNav(), - }), - }, - { - id: 'settings', - name: i18n.translate('xpack.enterpriseSearch.content.nav.settingsTitle', { - defaultMessage: 'Settings', - }), - ...generateNavLink({ - to: SETTINGS_PATH, - isRoot: true, - }), - }, - ], - }), - }, - { - id: 'app_search', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.appSearchTitle', { - defaultMessage: 'App Search', - }), - ...generateNavLink({ - to: APP_SEARCH_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - { - id: 'workplace_search', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.workplaceSearchTitle', { - defaultMessage: 'Workplace Search', - }), - ...generateNavLink({ - to: WORKPLACE_SEARCH_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - ]; - - return navItems; -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/page_template.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/page_template.test.tsx index e3385417f6151..b3aa172dd5bc0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/page_template.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/page_template.test.tsx @@ -5,8 +5,8 @@ * 2.0. */ -jest.mock('./nav', () => ({ - useEnterpriseSearchContentNav: () => [], +jest.mock('../../../shared/layout/nav', () => ({ + useEnterpriseSearchNav: () => [], })); import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/page_template.tsx index a4d5315c898d1..54dca0f8d921b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/page_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/layout/page_template.tsx @@ -10,10 +10,9 @@ import React from 'react'; import { ENTERPRISE_SEARCH_CONTENT_PLUGIN } from '../../../../../common/constants'; import { SetEnterpriseSearchChrome } from '../../../shared/kibana_chrome'; import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; +import { useEnterpriseSearchNav } from '../../../shared/layout'; import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry'; -import { useEnterpriseSearchContentNav } from './nav'; - export const EnterpriseSearchContentPageTemplate: React.FC = ({ children, pageChrome, @@ -25,7 +24,7 @@ export const EnterpriseSearchContentPageTemplate: React.FC = {...pageTemplateProps} solutionNav={{ name: ENTERPRISE_SEARCH_CONTENT_PLUGIN.NAME, - items: useEnterpriseSearchContentNav(), + items: useEnterpriseSearchNav(), }} setPageChrome={pageChrome && } > diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/constants.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/constants.ts index 1377a80cd9b38..4c37b03d705cb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/constants.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { EuiSelectOption } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; export const NEW_INDEX_TEMPLATE_TYPES: { [key: string]: string } = { @@ -60,9 +61,11 @@ export const DOCUMENTS_API_JSON_EXAMPLE = [ }, ]; -export const SUPPORTED_LANGUAGES = [ +export const UNIVERSAL_LANGUAGE_VALUE = ''; + +export const SUPPORTED_LANGUAGES: EuiSelectOption[] = [ { - value: 'Universal', + value: UNIVERSAL_LANGUAGE_VALUE, text: i18n.translate( 'xpack.enterpriseSearch.content.newIndex.supportedLanguages.universalDropDownOptionLabel', { @@ -201,5 +204,3 @@ export const SUPPORTED_LANGUAGES = [ ), }, ]; - -export const DEFAULT_LANGUAGE = 'Universal'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.test.ts index d12ab55a37f75..4f41bb7dcadcd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.test.ts @@ -7,13 +7,14 @@ import { LogicMounter } from '../../../__mocks__/kea_logic'; -import { DEFAULT_LANGUAGE } from './constants'; -import { NewSearchIndexLogic } from './new_search_index_logic'; +import { UNIVERSAL_LANGUAGE_VALUE } from './constants'; +import { NewSearchIndexLogic, NewSearchIndexValues } from './new_search_index_logic'; -const DEFAULT_VALUES = { +const DEFAULT_VALUES: NewSearchIndexValues = { rawName: '', name: '', - language: DEFAULT_LANGUAGE, + language: null, + languageSelectValue: UNIVERSAL_LANGUAGE_VALUE, }; describe('NewSearchIndexLogic', () => { @@ -25,13 +26,27 @@ describe('NewSearchIndexLogic', () => { }); describe('actions', () => { - describe('setLanguage', () => { + describe('setLanguageSelectValue', () => { it('sets language to the provided value', () => { mount(); - NewSearchIndexLogic.actions.setLanguage('English'); + NewSearchIndexLogic.actions.setLanguageSelectValue('en'); expect(NewSearchIndexLogic.values).toEqual({ ...DEFAULT_VALUES, - language: 'English', + language: 'en', + languageSelectValue: 'en', + }); + }); + + it('sets language to null when the universal language option is picked', () => { + mount({ + language: 'en', + languageSelectValue: 'en', + }); + NewSearchIndexLogic.actions.setLanguageSelectValue(UNIVERSAL_LANGUAGE_VALUE); + expect(NewSearchIndexLogic.values).toEqual({ + ...DEFAULT_VALUES, + language: null, + languageSelectValue: UNIVERSAL_LANGUAGE_VALUE, }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.ts index 7f3a9c767b590..d1727371db533 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.ts @@ -9,30 +9,33 @@ import { kea, MakeLogicType } from 'kea'; import { formatApiName } from '../../utils/format_api_name'; -import { DEFAULT_LANGUAGE } from './constants'; +import { UNIVERSAL_LANGUAGE_VALUE } from './constants'; +import { LanguageForOptimization } from './types'; +import { getLanguageForOptimizatioin } from './utils'; export interface NewSearchIndexValues { - language: string; + language: LanguageForOptimization; + languageSelectValue: string; name: string; rawName: string; } export interface NewSearchIndexActions { - setLanguage(language: string): { language: string }; + setLanguageSelectValue(language: string): { language: string }; setRawName(rawName: string): { rawName: string }; } export const NewSearchIndexLogic = kea>({ actions: { - setLanguage: (language) => ({ language }), + setLanguageSelectValue: (language) => ({ language }), setRawName: (rawName) => ({ rawName }), }, path: ['enterprise_search', 'content', 'new_search_index'], reducers: { - language: [ - DEFAULT_LANGUAGE, + languageSelectValue: [ + UNIVERSAL_LANGUAGE_VALUE, { - setLanguage: (_, { language }) => language, + setLanguageSelectValue: (_, { language }) => language ?? null, }, ], rawName: [ @@ -43,6 +46,10 @@ export const NewSearchIndexLogic = kea ({ + language: [ + () => [selectors.languageSelectValue], + (languageSelectValue) => getLanguageForOptimizatioin(languageSelectValue), + ], name: [() => [selectors.rawName], (rawName) => formatApiName(rawName)], }), }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.test.tsx index 8d7a41312a642..8274d6b7008f1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.test.tsx @@ -11,6 +11,7 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { UNIVERSAL_LANGUAGE_VALUE } from './constants'; import { NewSearchIndexTemplate, Props as NewSearchIndexTemplateProps, @@ -27,8 +28,13 @@ describe('NewSearchIndexTemplate', () => { beforeEach(() => { jest.clearAllMocks(); - setMockValues({ name: 'my-name', rawName: 'MY$_RAW_$NAME', language: 'Universal' }); - setMockActions({ makeRequest: jest.fn() }); + setMockValues({ + name: 'my-name', + rawName: 'MY$_RAW_$NAME', + language: null, + languageSelectValue: UNIVERSAL_LANGUAGE_VALUE, + }); + setMockActions({ makeRequest: jest.fn(), setLanguageSelectValue: jest.fn() }); }); it('renders children', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx index b86f48f82859d..b5696f6a4535c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx @@ -34,6 +34,7 @@ import { i18n } from '@kbn/i18n'; import { SUPPORTED_LANGUAGES } from './constants'; import { NewSearchIndexLogic } from './new_search_index_logic'; +import { LanguageForOptimization } from './types'; export interface Props { title: React.ReactNode; @@ -41,7 +42,7 @@ export interface Props { docsUrl: string; type: string; onNameChange?(name: string): void; - onSubmit(name: string, language: string): void; + onSubmit(name: string, language: LanguageForOptimization): void; buttonLoading?: boolean; formDisabled?: boolean; } @@ -55,8 +56,8 @@ export const NewSearchIndexTemplate: React.FC = ({ formDisabled, buttonLoading, }) => { - const { name, language, rawName } = useValues(NewSearchIndexLogic); - const { setRawName, setLanguage } = useActions(NewSearchIndexLogic); + const { name, language, rawName, languageSelectValue } = useValues(NewSearchIndexLogic); + const { setRawName, setLanguageSelectValue } = useActions(NewSearchIndexLogic); const handleNameChange = (e: ChangeEvent) => { setRawName(e.target.value); @@ -66,7 +67,7 @@ export const NewSearchIndexTemplate: React.FC = ({ }; const handleLanguageChange = (e: ChangeEvent) => { - setLanguage(e.target.value); + setLanguageSelectValue(e.target.value); }; return ( @@ -153,7 +154,7 @@ export const NewSearchIndexTemplate: React.FC = ({ diff --git a/x-pack/plugins/enterprise_search/common/types/connector_package.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/types.ts similarity index 74% rename from x-pack/plugins/enterprise_search/common/types/connector_package.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/types.ts index 2051360b733f4..bb6f172b80114 100644 --- a/x-pack/plugins/enterprise_search/common/types/connector_package.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/types.ts @@ -5,8 +5,4 @@ * 2.0. */ -export interface ConnectorPackage { - id: string; - indexName: string; - name: string; -} +export type LanguageForOptimization = string | null; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/utils.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/utils.test.ts new file mode 100644 index 0000000000000..b6068a76ccadc --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/utils.test.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { UNIVERSAL_LANGUAGE_VALUE } from './constants'; +import { getLanguageForOptimizatioin } from './utils'; + +describe('getLanguageForOptimizatioin', () => { + it('returns null for the universal language option', () => { + expect(getLanguageForOptimizatioin(UNIVERSAL_LANGUAGE_VALUE)).toEqual(null); + }); + + it('returns the language code for non-Universal languageoptions', () => { + expect(getLanguageForOptimizatioin('zh')).toEqual('zh'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/utils.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/utils.ts new file mode 100644 index 0000000000000..a8e7625db5c19 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/utils.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { UNIVERSAL_LANGUAGE_VALUE } from './constants'; +import { LanguageForOptimization } from './types'; + +// Enterprise Search expects the Universal language option to be represented by null +// but we can't use null as the value for an EuiSelectOption +export const getLanguageForOptimizatioin = (language: string): LanguageForOptimization => + language === UNIVERSAL_LANGUAGE_VALUE ? null : language; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/api_key_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/api_key_configuration.tsx index e53ffac0d4393..d4b8c82909e9f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/api_key_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/api_key_configuration.tsx @@ -16,7 +16,6 @@ import { EuiButton, EuiLink, EuiSpacer, - EuiCallOut, EuiConfirmModal, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -72,7 +71,7 @@ export const ApiKeyConfig: React.FC<{ hasApiKey: boolean; indexName: string }> = confirmButtonText={i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.apiKey.confirmModal.confirmButton.label', { - defaultMessage: 'Generate an Elasticsearch API key', + defaultMessage: 'Generate API key', } )} defaultFocusedButton="confirm" @@ -81,7 +80,7 @@ export const ApiKeyConfig: React.FC<{ hasApiKey: boolean; indexName: string }> = 'xpack.enterpriseSearch.content.indices.configurationConnector.apiKey.confirmModal.description', { defaultMessage: - 'Generating a new Elasticsearch API key will invalidate the previous key. Are you sure you want to generate a new Elasticsearch API key? This can not be undone.', + 'Generating a new API key will invalidate the previous key. Are you sure you want to generate a new API key? This can not be undone.', } )} @@ -96,7 +95,7 @@ export const ApiKeyConfig: React.FC<{ hasApiKey: boolean; indexName: string }> = 'xpack.enterpriseSearch.content.indices.configurationConnector.apiKey.description', { defaultMessage: - 'Keep your Elasticsearch API key somewhere safe while you configure your connector. Generating a new Elasticsearch API key will invalidate the previous key.', + 'Keep your Elasticsearch API key somewhere safe while you configure your connector.', } )} @@ -134,25 +133,6 @@ export const ApiKeyConfig: React.FC<{ hasApiKey: boolean; indexName: string }> = )} - {hasApiKey && ( - - - {i18n.translate( - 'xpack.enterpriseSearch.content.indices.configurationConnector.apiKey.warning.description', - { - defaultMessage: - 'Generating a new Elasticsearch API key will invalidate the previous key.', - } - )} - - - )} ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx index e41761e01dcfd..8243f901b70f8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx @@ -7,14 +7,11 @@ import React from 'react'; -import { useParams } from 'react-router-dom'; - import { useValues } from 'kea'; import { EuiText, EuiFlexGroup, - EuiButton, EuiFlexItem, EuiLink, EuiPanel, @@ -24,17 +21,26 @@ import { import { i18n } from '@kbn/i18n'; +import { ConnectorStatus } from '../../../../../../common/types/connectors'; +import { generateEncodedPath } from '../../../../shared/encode_path_params'; +import { EuiButtonTo } from '../../../../shared/react_router_helpers'; + import { GenerateConnectorApiKeyApiLogic } from '../../../api/connector_package/generate_connector_api_key_api_logic'; import { FetchIndexApiLogic } from '../../../api/index/fetch_index_api_logic'; +import { SEARCH_INDEX_TAB_PATH } from '../../../routes'; import { ApiKey } from '../../api_key/api_key'; +import { IndexNameLogic } from '../index_name_logic'; + +import { SearchIndexTabId } from '../search_index'; + import { ApiKeyConfig } from './api_key_configuration'; import { ConnectorConfigurationConfig } from './connector_configuration_config'; export const ConnectorConfiguration: React.FC = () => { const { data: apiKeyData } = useValues(GenerateConnectorApiKeyApiLogic); const { data: indexData } = useValues(FetchIndexApiLogic); - const { indexName } = useParams<{ indexName: string }>(); + const { indexName } = useValues(IndexNameLogic); const indexId = indexData?.connector?.id ?? ''; const hasApiKey = !!(indexData?.connector?.api_key_id ?? apiKeyData); @@ -42,7 +48,9 @@ export const ConnectorConfiguration: React.FC = () => { const ConnectorConfig: React.FC = () => indexData?.connector ? ( @@ -50,6 +58,41 @@ export const ConnectorConfiguration: React.FC = () => { <> ); + const ScheduleStep: React.FC = () => ( + + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.scheduleSync.description', + { + defaultMessage: + 'To start a sync you need to set a schedule. Once done your documents will begin to sync.', + } + )} + + + + + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.steps.schedule.button.label', + { + defaultMessage: 'Set schedule and sync', + } + )} + + + + + + ); + const ConnectorPackage: React.FC = () => ( @@ -65,14 +108,14 @@ export const ConnectorConfiguration: React.FC = () => { - + {i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.connectorPackage.button.label', { defaultMessage: 'Clone and deploy connector package', } )} - + @@ -82,7 +125,7 @@ export const ConnectorConfiguration: React.FC = () => { label={i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.connectorPackage.apiKey.label', { - defaultMessage: 'Connector package ID', + defaultMessage: 'Connector ID', } )} /> @@ -116,7 +159,11 @@ export const ConnectorConfiguration: React.FC = () => { }, { children: , - status: 'incomplete', + status: + !indexData?.connector?.status || + indexData.connector.status === ConnectorStatus.CREATED + ? 'incomplete' + : 'complete', title: i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.steps.deployConnector.title', { @@ -127,7 +174,11 @@ export const ConnectorConfiguration: React.FC = () => { }, { children: , - status: 'incomplete', + status: + indexData?.connector?.status && + indexData.connector.status === ConnectorStatus.CONNECTED + ? 'complete' + : 'incomplete', title: i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.steps.connect.title', { @@ -136,6 +187,17 @@ export const ConnectorConfiguration: React.FC = () => { ), titleSize: 'xs', }, + { + children: , + status: indexData?.connector?.scheduling.enabled ? 'complete' : 'incomplete', + title: i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.steps.schedule.title', + { + defaultMessage: 'Set a schedule and start a sync', + } + ), + titleSize: 'xs', + }, ]} /> @@ -191,6 +253,16 @@ export const ConnectorConfiguration: React.FC = () => { )} + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.support.feedback.label', + { + defaultMessage: 'Custom connector feedback', + } + )} + + diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_config.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_config.tsx index 233207d6cf427..c1927aeea0dfc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_config.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_config.tsx @@ -12,32 +12,38 @@ import { useActions, useValues } from 'kea'; import { EuiButton, EuiButtonEmpty, + EuiCodeBlock, EuiDescriptionList, EuiFieldText, EuiFlexGroup, EuiFlexItem, EuiForm, EuiFormRow, + EuiSpacer, EuiText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Status } from '../../../../../../common/types/api'; +import { ConnectorConfiguration } from '../../../../../../common/types/connectors'; import { isNotNullish } from '../../../../../../common/utils/is_not_nullish'; import { ConnectorConfigurationApiLogic } from '../../../api/connector_package/update_connector_configuration_api_logic'; -import { ConnectorConfiguration } from '../../../api/index/fetch_index_api_logic'; import { ConnectorConfigurationLogic } from './connector_configuration_logic'; interface ConnectorConfigurationConfigArgs { + apiKey: string | undefined; configuration: ConnectorConfiguration; + connectorId: string; indexId: string; indexName: string; } export const ConnectorConfigurationConfig: React.FC = ({ + apiKey, configuration, + connectorId, indexId, indexName, }) => { @@ -54,6 +60,19 @@ export const ConnectorConfigurationConfig: React.FC + {`${ + apiKey + ? `elasticsearch: + api_key: "${apiKey}" +` + : '' + }connector_package_id: "${connectorId}" +`} + + ); + const form = ( { @@ -122,6 +141,7 @@ export const ConnectorConfigurationConfig: React.FC ({ description: value ?? '--', title: label })); + const display = ( @@ -158,6 +178,19 @@ export const ConnectorConfigurationConfig: React.FC + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.yml.description', + { + defaultMessage: + 'Use this YAML sample with your Elastic API key and Connector id to get going faster', + } + )} + + + {ymlBlock} + {displayList.length > 0 && fields} ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts index cb4bfe2e5621f..ecbbb2616f88b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts @@ -9,6 +9,7 @@ import { kea, MakeLogicType } from 'kea'; import { i18n } from '@kbn/i18n'; +import { ConnectorConfiguration } from '../../../../../../common/types/connectors'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; import { clearFlashMessages, @@ -21,7 +22,6 @@ import { PostConnectorConfigurationArgs, PostConnectorConfigurationResponse, } from '../../../api/connector_package/update_connector_configuration_api_logic'; -import { ConnectorConfiguration } from '../../../api/index/fetch_index_api_logic'; type ConnectorConfigurationActions = Pick< Actions, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.ts index 6ab8072d27ecf..a6adb47ff88ee 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling_logic.ts @@ -9,6 +9,7 @@ import { kea, MakeLogicType } from 'kea'; import { i18n } from '@kbn/i18n'; +import { ConnectorScheduling } from '../../../../../../common/types/connectors'; import { Actions } from '../../../../shared/api_logic/create_api_logic'; import { clearFlashMessages, @@ -20,7 +21,6 @@ import { UpdateConnectorSchedulingApiLogic, UpdateConnectorSchedulingArgs, } from '../../../api/connector_package/update_connector_scheduling_api_logic'; -import { ConnectorScheduling } from '../../../api/index/fetch_index_api_logic'; type ConnectorSchedulingActions = Pick< Actions, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler_total_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler_total_stats.tsx new file mode 100644 index 0000000000000..367932d987900 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler_total_stats.tsx @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues } from 'kea'; + +import { i18n } from '@kbn/i18n'; + +import { CrawlerLogic } from './crawler/crawler_logic'; +import { TotalStats } from './total_stats'; + +export const CrawlerTotalStats: React.FC = () => { + const { domains, dataLoading } = useValues(CrawlerLogic); + + const additionalItems = [ + { + description: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.domainCountCardLabel', + { + defaultMessage: 'Domain count', + } + ), + isLoading: dataLoading, + title: domains.length, + }, + ]; + + return ( + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx index 989cd6570e3ea..774783f9da473 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/overview.tsx @@ -11,16 +11,18 @@ import { useValues } from 'kea'; import { EuiSpacer } from '@elastic/eui'; -import { Status } from '../../../../../common/types/api'; +import { i18n } from '@kbn/i18n'; + import { FetchIndexApiLogic } from '../../api/index/fetch_index_api_logic'; import { CrawlDetailsFlyout } from './crawler/crawl_details_flyout/crawl_details_flyout'; import { CrawlRequestsPanel } from './crawler/crawl_requests_panel/crawl_requests_panel'; +import { CrawlerTotalStats } from './crawler_total_stats'; import { GenerateApiKeyPanel } from './generate_api_key_panel'; import { TotalStats } from './total_stats'; export const SearchIndexOverview: React.FC = () => { - const { data, status } = useValues(FetchIndexApiLogic); + const { data } = useValues(FetchIndexApiLogic); const isCrawler = typeof data?.crawler !== 'undefined'; const isConnector = typeof data?.connector !== 'undefined'; @@ -29,12 +31,25 @@ export const SearchIndexOverview: React.FC = () => { return ( <> - {status === Status.SUCCESS && data && ( + {isCrawler ? ( + + ) : ( )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/total_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/total_stats.tsx index a6ef7ffad409d..b3ed64e1b6e9f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/total_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/total_stats.tsx @@ -7,45 +7,72 @@ import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat } from '@elastic/eui'; +import { useValues } from 'kea'; + +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat, EuiStatProps } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { Status } from '../../../../../common/types/api'; + +import { CustomFormattedTimestamp } from '../../../shared/custom_formatted_timestamp/custom_formatted_timestamp'; +import { FetchIndexApiLogic } from '../../api/index/fetch_index_api_logic'; interface TotalStatsProps { - lastUpdated: string; - documentCount: number; - indexHealth: string; + additionalItems?: EuiStatProps[]; ingestionType: string; } -export const TotalStats: React.FC = ({ - lastUpdated, - documentCount, - indexHealth, - ingestionType, -}) => { +export const TotalStats: React.FC = ({ ingestionType, additionalItems = [] }) => { + const { data, status } = useValues(FetchIndexApiLogic); + const documentCount = data?.index.total.docs.count ?? 0; + const lastUpdated = ( + + ); + const isLoading = status !== Status.SUCCESS; + const stats: EuiStatProps[] = [ + { + description: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.ingestionTypeCardLabel', + { + defaultMessage: 'Ingestion type', + } + ), + isLoading, + title: ingestionType, + }, + { + description: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.documentCountCardLabel', + { + defaultMessage: 'Document count', + } + ), + isLoading, + title: documentCount, + }, + { + description: i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.totalStats.lastUpdatedCardLabel', + { + defaultMessage: 'Last updated', + } + ), + isLoading, + title: lastUpdated, + }, + ...additionalItems, + ]; + return ( - - - - - - - - - - - - - - - - - - - - - - + {stats.map((item, index) => ( + + + + + + ))} ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/types.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/types.ts index 5ada08728e468..b6c88caf63ed6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/types.ts @@ -12,11 +12,35 @@ import { HealthStatus } from '@elastic/elasticsearch/lib/api/types'; +import { Connector } from '../../../common/types/connectors'; + export interface SearchIndex { - name: string; - elasticsearch_index_name: string; + data_ingestion: 'connected' | 'incomplete'; document_count: number; + elasticsearch_index_name: string; health: HealthStatus; - data_ingestion: 'connected' | 'incomplete'; + name: string; + storage: string; } + +export interface Crawler { + domains: []; +} + +export interface IndexData { + connector?: Connector; + crawler?: Crawler; + index: { + aliases: string[]; + health: string; + name: string; + total: { + docs: { + count: number; + deleted: number; + }; + }; + uuid: string; + }; +} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/index.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/index.ts index ea69823f82b87..261dd353b0a35 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/index.ts @@ -5,6 +5,5 @@ * 2.0. */ -export { useEnterpriseSearchOverviewNav } from './nav'; export { EnterpriseSearchOverviewPageTemplate } from './page_template'; export { EnterpriseSearchOverviewHeaderActions } from './kibana_header_actions'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/nav.test.tsx deleted file mode 100644 index 411bda5dfe2be..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/nav.test.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -jest.mock('../../../shared/layout', () => ({ - generateNavLink: jest.fn(({ to, items }) => ({ href: to, items })), -})); - -import { useEnterpriseSearchOverviewNav } from '.'; - -describe('useEnterpriseSearchOverviewNav', () => { - it('returns an array of top-level Enterprise Search nav items', () => { - expect(useEnterpriseSearchOverviewNav()).toEqual([ - { - id: 'es_overview', - name: 'Overview', - emphasize: true, - isSelected: true, - href: '/app/enterprise_search/overview', - }, - { - id: 'content', - name: 'Content', - emphasize: true, - href: '/app/enterprise_search/content', - }, - { - id: 'app_search', - name: 'App Search', - emphasize: true, - href: '/app/enterprise_search/app_search', - }, - { - id: 'workplace_search', - name: 'Workplace Search', - emphasize: true, - href: '/app/enterprise_search/workplace_search', - }, - ]); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/nav.tsx deleted file mode 100644 index 294e8f0e87a32..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/nav.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiSideNavItemType } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { - APP_SEARCH_PLUGIN, - ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, - ENTERPRISE_SEARCH_CONTENT_PLUGIN, - WORKPLACE_SEARCH_PLUGIN, -} from '../../../../../common/constants'; -import { generateNavLink } from '../../../shared/layout'; - -export const useEnterpriseSearchOverviewNav = () => { - const navItems: Array> = [ - { - id: 'es_overview', - isSelected: true, - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.enterpriseSearchOverviewTitle', { - defaultMessage: 'Overview', - }), - href: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, - }, - { - id: 'content', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.contentTitle', { - defaultMessage: 'Content', - }), - ...generateNavLink({ - to: ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - { - id: 'app_search', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.appSearchTitle', { - defaultMessage: 'App Search', - }), - ...generateNavLink({ - to: APP_SEARCH_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - { - id: 'workplace_search', - emphasize: true, - name: i18n.translate('xpack.enterpriseSearch.content.nav.workplaceSearchTitle', { - defaultMessage: 'Workplace Search', - }), - ...generateNavLink({ - to: WORKPLACE_SEARCH_PLUGIN.URL, - shouldNotCreateHref: true, - }), - }, - ]; - - return navItems; -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/page_template.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/page_template.test.tsx index 0a7019da3fdd0..791a9bbab3a11 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/page_template.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/page_template.test.tsx @@ -5,8 +5,8 @@ * 2.0. */ -jest.mock('./nav', () => ({ - useEnterpriseSearchOverviewNav: () => [], +jest.mock('../../../shared/layout/nav', () => ({ + useEnterpriseSearchNav: () => [], })); import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/page_template.tsx index 2f914d01ce8be..8902788edb329 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/page_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/layout/page_template.tsx @@ -10,10 +10,9 @@ import React from 'react'; import { ENTERPRISE_SEARCH_CONTENT_PLUGIN } from '../../../../../common/constants'; import { SetEnterpriseSearchChrome } from '../../../shared/kibana_chrome'; import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; +import { useEnterpriseSearchNav } from '../../../shared/layout'; import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry'; -import { useEnterpriseSearchOverviewNav } from './nav'; - export const EnterpriseSearchOverviewPageTemplate: React.FC = ({ children, pageChrome, @@ -25,7 +24,7 @@ export const EnterpriseSearchOverviewPageTemplate: React.FC = {...pageTemplateProps} solutionNav={{ name: ENTERPRISE_SEARCH_CONTENT_PLUGIN.NAME, - items: useEnterpriseSearchOverviewNav(), + items: useEnterpriseSearchNav(), }} setPageChrome={pageChrome && } > diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx index 3a1e52e8d8afd..b958fb3925d4e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.tsx @@ -24,7 +24,6 @@ import { Chat } from '@kbn/cloud-plugin/public'; import { i18n } from '@kbn/i18n'; import { - KibanaPageTemplate, KibanaPageTemplateSolutionNavAvatar, NO_DATA_PAGE_TEMPLATE_PROPS, } from '@kbn/kibana-react-plugin/public'; @@ -38,6 +37,7 @@ import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/ import AppSearchImage from '../../assets/app_search.png'; import WorkplaceSearchImage from '../../assets/workplace_search.png'; import { ElasticsearchCard } from '../elasticsearch_card'; +import { EnterpriseSearchOverviewPageTemplate } from '../layout'; import { LicenseCallout } from '../license_callout'; import { ProductCard } from '../product_card'; import { SetupGuideCta } from '../setup_guide'; @@ -152,7 +152,7 @@ export const ProductSelector: React.FC = ({ /> ); return ( - + @@ -186,6 +186,6 @@ export const ProductSelector: React.FC = ({ {shouldShowEnterpriseSearchCards ? productCards : insufficientAccessMessage} - + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/custom_formatted_timestamp/custom_formatted_timestamp.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/custom_formatted_timestamp/custom_formatted_timestamp.tsx index 7e65493ec7e08..c9893ecdf1547 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/custom_formatted_timestamp/custom_formatted_timestamp.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/custom_formatted_timestamp/custom_formatted_timestamp.tsx @@ -12,7 +12,7 @@ import { FormattedRelative } from '@kbn/i18n-react'; import { FormattedDateTime } from '../formatted_date_time'; interface CustomFormattedTimestampProps { - timestamp: string; + timestamp: string | number | Date; } export const CustomFormattedTimestamp: React.FC = ({ diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts index 873357e0528af..07aa3974b6479 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts @@ -7,12 +7,11 @@ import { FC } from 'react'; -import { History } from 'history'; import { kea, MakeLogicType } from 'kea'; import { ChartsPluginStart } from '@kbn/charts-plugin/public'; import { CloudSetup } from '@kbn/cloud-plugin/public'; -import { ApplicationStart, ChromeBreadcrumb } from '@kbn/core/public'; +import { ApplicationStart, ChromeBreadcrumb, ScopedHistory } from '@kbn/core/public'; import { SecurityPluginStart } from '@kbn/security-plugin/public'; import { HttpLogic } from '../http'; @@ -24,7 +23,7 @@ type RequiredFieldsOnly = { interface KibanaLogicProps { config: { host?: string }; // Kibana core - history: History; + history: ScopedHistory; navigateToUrl: RequiredFieldsOnly; setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void; setChromeIsVisible(isVisible: boolean): void; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts index 790d72943a1bc..b137029defb34 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/index.ts @@ -8,3 +8,4 @@ export type { PageTemplateProps } from './page_template'; export { EnterpriseSearchPageTemplateWrapper } from './page_template'; export { generateNavLink } from './nav_link_helpers'; +export { useEnterpriseSearchNav } from './nav'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx new file mode 100644 index 0000000000000..60f51b8d6b6f2 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +jest.mock('./nav_link_helpers', () => ({ + generateNavLink: jest.fn(({ to, items }) => ({ href: to, items })), +})); + +import { useEnterpriseSearchNav } from './nav'; + +describe('useEnterpriseSearchContentNav', () => { + it('returns an array of top-level Enterprise Search nav items', () => { + expect(useEnterpriseSearchNav()).toEqual([ + { + href: '/app/enterprise_search/overview', + id: 'es_overview', + name: 'Overview', + }, + { + id: 'content', + items: [ + { + href: '/app/enterprise_search/content/search_indices', + id: 'search_indices', + name: 'Indices', + }, + ], + name: 'Content', + }, + { + id: 'search_experiences', + items: [ + { + href: '/app/enterprise_search/elasticsearch', + id: 'elasticsearch', + name: 'Elasticsearch', + }, + { + href: '/app/enterprise_search/app_search', + id: 'app_search', + name: 'App Search', + }, + { + href: '/app/enterprise_search/workplace_search', + id: 'workplace_search', + name: 'Workplace Search', + }, + ], + name: 'Search experiences', + }, + ]); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx new file mode 100644 index 0000000000000..f97253585505b --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiSideNavItemType } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { + APP_SEARCH_PLUGIN, + ELASTICSEARCH_PLUGIN, + ENTERPRISE_SEARCH_CONTENT_PLUGIN, + ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, + WORKPLACE_SEARCH_PLUGIN, +} from '../../../../common/constants'; +import { SEARCH_INDICES_PATH } from '../../enterprise_search_content/routes'; + +import { generateNavLink } from './nav_link_helpers'; + +export const useEnterpriseSearchNav = () => { + const navItems: Array> = [ + { + id: 'es_overview', + name: i18n.translate('xpack.enterpriseSearch.nav.enterpriseSearchOverviewTitle', { + defaultMessage: 'Overview', + }), + ...generateNavLink({ + shouldNotCreateHref: true, + to: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.URL, + }), + }, + { + id: 'content', + items: [ + { + id: 'search_indices', + name: i18n.translate('xpack.enterpriseSearch.nav.searchIndicesTitle', { + defaultMessage: 'Indices', + }), + ...generateNavLink({ + shouldNotCreateHref: true, + shouldShowActiveForSubroutes: true, + to: ENTERPRISE_SEARCH_CONTENT_PLUGIN.URL + SEARCH_INDICES_PATH, + }), + }, + ], + name: i18n.translate('xpack.enterpriseSearch.nav.contentTitle', { + defaultMessage: 'Content', + }), + }, + { + id: 'search_experiences', + items: [ + { + id: 'elasticsearch', + name: i18n.translate('xpack.enterpriseSearch.nav.elasticsearchTitle', { + defaultMessage: 'Elasticsearch', + }), + ...generateNavLink({ + shouldNotCreateHref: true, + to: ELASTICSEARCH_PLUGIN.URL, + }), + }, + { + id: 'app_search', + name: i18n.translate('xpack.enterpriseSearch.nav.appSearchTitle', { + defaultMessage: 'App Search', + }), + ...generateNavLink({ + shouldNotCreateHref: true, + to: APP_SEARCH_PLUGIN.URL, + }), + }, + { + id: 'workplace_search', + name: i18n.translate('xpack.enterpriseSearch.nav.workplaceSearchTitle', { + defaultMessage: 'Workplace Search', + }), + ...generateNavLink({ + shouldNotCreateHref: true, + to: WORKPLACE_SEARCH_PLUGIN.URL, + }), + }, + ], + name: i18n.translate('xpack.enterpriseSearch.nav.searchExperiencesTitle', { + defaultMessage: 'Search experiences', + }), + }, + ]; + + return navItems; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav_link_helpers.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav_link_helpers.test.ts index 8cfca3bade993..fff28345bb1bb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav_link_helpers.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav_link_helpers.test.ts @@ -6,14 +6,14 @@ */ import { mockKibanaValues } from '../../__mocks__/kea_logic'; +import '../../__mocks__/react_router'; -jest.mock('../react_router_helpers', () => ({ - generateReactRouterProps: ({ to }: { to: string }) => ({ - href: `/app/enterprise_search${to}`, - onClick: () => mockKibanaValues.navigateToUrl(to), - }), +jest.mock('../react_router_helpers/link_events', () => ({ + letBrowserHandleEvent: jest.fn(), })); +import { letBrowserHandleEvent } from '../react_router_helpers/link_events'; + import { generateNavLink, getNavLinkActive } from './nav_link_helpers'; describe('generateNavLink', () => { @@ -23,6 +23,8 @@ describe('generateNavLink', () => { }); it('generates React Router props for use within an EuiSideNavItem obj', () => { + (letBrowserHandleEvent as jest.Mock).mockReturnValueOnce(false); + const navItem = generateNavLink({ to: '/test' }); expect(navItem).toEqual({ @@ -31,8 +33,10 @@ describe('generateNavLink', () => { isSelected: false, }); - navItem.onClick({} as any); - expect(mockKibanaValues.navigateToUrl).toHaveBeenCalledWith('/test'); + navItem.onClick({ preventDefault: jest.fn() } as any); + expect(mockKibanaValues.navigateToUrl).toHaveBeenCalledWith('/test', { + shouldNotCreateHref: false, + }); }); describe('isSelected / getNavLinkActive', () => { @@ -50,19 +54,20 @@ describe('generateNavLink', () => { expect(isSelected).toEqual(false); }); - describe('isRoot', () => { - it('returns true if the current path is "/"', () => { - mockKibanaValues.history.location.pathname = '/'; - const isSelected = getNavLinkActive({ to: '/overview', isRoot: true }); - - expect(isSelected).toEqual(true); + it('returns true when to includes a basePath and shouldNotCreateHref=true', () => { + mockKibanaValues.history.location.pathname = '/test'; + const isSelected = getNavLinkActive({ + shouldNotCreateHref: true, + to: '/app/enterprise_search/test', }); + + expect(isSelected).toEqual(true); }); describe('shouldShowActiveForSubroutes', () => { it('returns true if the current path is a subroute of the passed path', () => { mockKibanaValues.history.location.pathname = '/hello/world'; - const isSelected = getNavLinkActive({ to: '/hello', shouldShowActiveForSubroutes: true }); + const isSelected = getNavLinkActive({ shouldShowActiveForSubroutes: true, to: '/hello' }); expect(isSelected).toEqual(true); }); @@ -76,9 +81,9 @@ describe('generateNavLink', () => { it('returns false if subroutes already have their own items subnav (with active state)', () => { mockKibanaValues.history.location.pathname = '/items/123/settings'; const isSelected = getNavLinkActive({ - to: '/items', - shouldShowActiveForSubroutes: true, items: [{ id: 'settings', name: 'Settings' }], + shouldShowActiveForSubroutes: true, + to: '/items', }); expect(isSelected).toEqual(false); @@ -86,7 +91,7 @@ describe('generateNavLink', () => { it('returns false if not a valid subroute', () => { mockKibanaValues.history.location.pathname = '/hello/world'; - const isSelected = getNavLinkActive({ to: '/world', shouldShowActiveForSubroutes: true }); + const isSelected = getNavLinkActive({ shouldShowActiveForSubroutes: true, to: '/world' }); expect(isSelected).toEqual(false); }); @@ -97,11 +102,22 @@ describe('generateNavLink', () => { expect(isSelected).toEqual(false); }); + + it('returns true when to includes a basePath and shouldNotCreateHref=true', () => { + mockKibanaValues.history.location.pathname = '/hello/world'; + const isSelected = getNavLinkActive({ + shouldNotCreateHref: true, + shouldShowActiveForSubroutes: true, + to: '/app/enterprise_search/hello', + }); + + expect(isSelected).toEqual(true); + }); }); }); it('optionally passes items', () => { - const navItem = generateNavLink({ to: '/test', items: [] }); + const navItem = generateNavLink({ items: [], to: '/test' }); expect(navItem.items).toEqual([]); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav_link_helpers.ts b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav_link_helpers.ts index 9caf58886c52e..f086433c9fc0e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav_link_helpers.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav_link_helpers.ts @@ -11,38 +11,47 @@ import { stripTrailingSlash } from '../../../../common/strip_slashes'; import { KibanaLogic } from '../kibana'; import { generateReactRouterProps, ReactRouterProps } from '../react_router_helpers'; +import { GeneratedReactRouterProps } from '../react_router_helpers/generate_react_router_props'; interface Params { - to: string; - isRoot?: boolean; - shouldShowActiveForSubroutes?: boolean; items?: Array>; // Primarily passed if using `items` to determine isSelected - if not, you can just set `items` outside of this helper + shouldShowActiveForSubroutes?: boolean; + to: string; } -export const generateNavLink = ({ to, items, ...rest }: Params & ReactRouterProps) => { - return { - ...generateReactRouterProps({ to, ...rest }), - isSelected: getNavLinkActive({ to, items, ...rest }), - items, +type NavLinkProps = GeneratedReactRouterProps & + Pick, 'isSelected' | 'items'>; + +export const generateNavLink = ({ + items, + ...rest +}: Params & ReactRouterProps): NavLinkProps => { + const linkProps = { + ...generateReactRouterProps({ ...rest }), + isSelected: getNavLinkActive({ items, ...rest }), }; + return items ? { ...linkProps, items } : linkProps; }; export const getNavLinkActive = ({ to, - isRoot = false, shouldShowActiveForSubroutes = false, items = [], -}: Params): boolean => { + shouldNotCreateHref = false, +}: Params & ReactRouterProps): boolean => { const { pathname } = KibanaLogic.values.history.location; const currentPath = stripTrailingSlash(pathname); + const { href: currentPathHref } = generateReactRouterProps({ + shouldNotCreateHref: false, + to: currentPath, + }); + const { href: toHref } = generateReactRouterProps({ shouldNotCreateHref, to }); - if (currentPath === to) return true; - - if (isRoot && currentPath === '') return true; + if (currentPathHref === toHref) return true; if (shouldShowActiveForSubroutes) { if (items.length) return false; // If a nav link has sub-nav items open, never show it as active - if (currentPath.startsWith(to)) return true; + if (currentPathHref.startsWith(toHref)) return true; } return false; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/generate_react_router_props.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/generate_react_router_props.test.ts index 05e00eb8cc3a6..309f94fcf55b4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/generate_react_router_props.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/generate_react_router_props.test.ts @@ -31,7 +31,7 @@ describe('generateReactRouterProps', () => { }); describe('onClick', () => { - it('prevents default navigation and uses React Router history', () => { + it('prevents default navigation and uses React Router history for internal links', () => { const mockEvent = { button: 0, target: { getAttribute: () => '_self' }, @@ -42,11 +42,33 @@ describe('generateReactRouterProps', () => { onClick(mockEvent); expect(mockEvent.preventDefault).toHaveBeenCalled(); - expect(mockKibanaValues.navigateToUrl).toHaveBeenCalled(); + expect(mockKibanaValues.navigateToUrl).toHaveBeenCalledWith('/test', { + shouldNotCreateHref: false, + }); + }); + + it('prevents default navigation and uses React Router history for cross-app links', () => { + const mockEvent = { + button: 0, + target: { getAttribute: () => '_self' }, + preventDefault: jest.fn(), + } as any; + + const { onClick } = generateReactRouterProps({ + to: '/app/enterprise_search/test', + shouldNotCreateHref: true, + }); + onClick(mockEvent); + + expect(mockEvent.preventDefault).toHaveBeenCalled(); + expect(mockKibanaValues.navigateToUrl).toHaveBeenCalledWith('/app/enterprise_search/test', { + shouldNotCreateHref: true, + }); }); it('does not prevent default browser behavior on new tab/window clicks', () => { const mockEvent = { + preventDefault: jest.fn(), shiftKey: true, target: { getAttribute: () => '_blank' }, } as any; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/generate_react_router_props.ts b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/generate_react_router_props.ts index 994468721856f..2ef7f556eb2d1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/generate_react_router_props.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/generate_react_router_props.ts @@ -7,6 +7,8 @@ import React from 'react'; +import { EuiSideNavItemType } from '@elastic/eui'; + import { HttpLogic } from '../http'; import { KibanaLogic } from '../kibana'; @@ -29,11 +31,15 @@ export interface ReactRouterProps { shouldNotCreateHref?: boolean; } +export type GeneratedReactRouterProps = Required< + Pick, 'href' | 'onClick'> +>; + export const generateReactRouterProps = ({ to, onClick, - shouldNotCreateHref, -}: ReactRouterProps) => { + shouldNotCreateHref = false, +}: ReactRouterProps): GeneratedReactRouterProps => { const { navigateToUrl, history } = KibanaLogic.values; const { http } = HttpLogic.values; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx index 1e73c6156619e..3337493b54018 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.test.tsx @@ -30,7 +30,7 @@ describe('useWorkplaceSearchNav', () => { { id: 'root', name: 'Overview', - href: '/', + href: '', }, { id: 'sources', diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx index 05ec569dcd292..f259c0ed7349c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/components/layout/nav.tsx @@ -26,7 +26,7 @@ export const useWorkplaceSearchNav = () => { { id: 'root', name: NAV.OVERVIEW, - ...generateNavLink({ to: '/', isRoot: true }), + ...generateNavLink({ to: '' }), }, { id: 'sources', diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts index aa4290e241a2f..fbc8924e499cd 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts @@ -8,6 +8,7 @@ import { IScopedClusterClient } from '@kbn/core/server'; import { CONNECTORS_INDEX } from '../..'; +import { ConnectorStatus } from '../../../common/types/connectors'; import { setupConnectorsIndices } from '../../index_management/setup_indices'; @@ -42,13 +43,12 @@ describe('addConnector lib function', () => { document: { api_key_id: null, configuration: {}, - created_at: null, index_name: 'index_name', last_seen: null, last_synced: null, scheduling: { enabled: false, interval: '* * * * *' }, service_type: null, - status: 'not connected', + status: ConnectorStatus.CREATED, sync_error: null, sync_now: false, sync_status: null, @@ -73,13 +73,12 @@ describe('addConnector lib function', () => { document: { api_key_id: null, configuration: {}, - created_at: null, index_name: 'index_name', last_seen: null, last_synced: null, scheduling: { enabled: false, interval: '* * * * *' }, service_type: null, - status: 'not connected', + status: ConnectorStatus.CREATED, sync_error: null, sync_now: false, sync_status: null, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts index c416d698157da..8314b3ac059b0 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts @@ -8,13 +8,18 @@ import { IScopedClusterClient } from '@kbn/core/server'; import { CONNECTORS_INDEX } from '../..'; +import { ConnectorDocument, ConnectorStatus } from '../../../common/types/connectors'; import { setupConnectorsIndices } from '../../index_management/setup_indices'; -import { Connector } from '../../types/connector'; import { isIndexNotFoundException } from '../../utils/identify_exceptions'; +export const createConnectorsIndex = async (client: IScopedClusterClient): Promise => { + const index = CONNECTORS_INDEX; + await client.asCurrentUser.indices.create({ index }); +}; + const createConnector = async ( index: string, - document: Connector, + document: ConnectorDocument, client: IScopedClusterClient ): Promise<{ id: string; index_name: string }> => { const result = await client.asCurrentUser.index({ @@ -31,16 +36,15 @@ export const addConnector = async ( input: { index_name: string } ): Promise<{ id: string; index_name: string }> => { const index = CONNECTORS_INDEX; - const document: Connector = { + const document: ConnectorDocument = { api_key_id: null, configuration: {}, - created_at: null, index_name: input.index_name, last_seen: null, last_synced: null, scheduling: { enabled: false, interval: '* * * * *' }, service_type: null, - status: 'not connected', + status: ConnectorStatus.CREATED, sync_error: null, sync_now: false, sync_status: null, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/fetch_connectors.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/fetch_connectors.ts index 6c33baa1064c2..eaeeaff88003a 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/fetch_connectors.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/fetch_connectors.ts @@ -8,18 +8,18 @@ import { IScopedClusterClient } from '@kbn/core/server'; import { CONNECTORS_INDEX } from '../..'; +import { Connector, ConnectorDocument } from '../../../common/types/connectors'; import { isNotNullish } from '../../../common/utils/is_not_nullish'; import { setupConnectorsIndices } from '../../index_management/setup_indices'; -import { Connector, ConnectorWithId } from '../../types/connector'; import { isIndexNotFoundException } from '../../utils/identify_exceptions'; export const fetchConnectorById = async ( client: IScopedClusterClient, connectorId: string -): Promise => { +): Promise => { try { - const connectorResult = await client.asCurrentUser.get({ + const connectorResult = await client.asCurrentUser.get({ id: connectorId, index: CONNECTORS_INDEX, }); @@ -37,9 +37,9 @@ export const fetchConnectorById = async ( export const fetchConnectorByIndexName = async ( client: IScopedClusterClient, indexName: string -): Promise => { +): Promise => { try { - const connectorResult = await client.asCurrentUser.search({ + const connectorResult = await client.asCurrentUser.search({ index: CONNECTORS_INDEX, query: { term: { 'index_name.keyword': indexName } }, }); @@ -58,9 +58,9 @@ export const fetchConnectorByIndexName = async ( } }; -export const fetchConnectors = async (client: IScopedClusterClient): Promise => { +export const fetchConnectors = async (client: IScopedClusterClient): Promise => { try { - const connectorResult = await client.asCurrentUser.search({ + const connectorResult = await client.asCurrentUser.search({ from: 0, index: CONNECTORS_INDEX, query: { match_all: {} }, @@ -69,7 +69,7 @@ export const fetchConnectors = async (client: IScopedClusterClient): Promise= 1000) { - const newConnectorResult = await client.asCurrentUser.search({ + const newConnectorResult = await client.asCurrentUser.search({ from: 0, index: CONNECTORS_INDEX, query: { match_all: {} }, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.ts index 4ad3b0c993c2a..77feda4b7ff5b 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.ts @@ -10,21 +10,29 @@ import { i18n } from '@kbn/i18n'; import { CONNECTORS_INDEX } from '../..'; -import { Connector, ConnectorConfiguration } from '../../types/connector'; +import { + ConnectorConfiguration, + ConnectorDocument, + ConnectorStatus, +} from '../../../common/types/connectors'; export const updateConnectorConfiguration = async ( client: IScopedClusterClient, connectorId: string, configuration: ConnectorConfiguration ) => { - const connectorResult = await client.asCurrentUser.get({ + const connectorResult = await client.asCurrentUser.get({ id: connectorId, index: CONNECTORS_INDEX, }); const connector = connectorResult._source; if (connector) { - return await client.asCurrentUser.index({ - document: { ...connector, configuration }, + const status = + connector.status === ConnectorStatus.NEEDS_CONFIGURATION + ? ConnectorStatus.CONFIGURED + : connector.status; + return await client.asCurrentUser.index({ + document: { ...connector, configuration, status }, id: connectorId, index: CONNECTORS_INDEX, }); diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_scheduling.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_scheduling.ts index 4fde352d4030e..3fe7e602148b5 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_scheduling.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_scheduling.ts @@ -10,20 +10,20 @@ import { i18n } from '@kbn/i18n'; import { CONNECTORS_INDEX } from '../..'; -import { Connector, ConnectorScheduling } from '../../types/connector'; +import { ConnectorDocument, ConnectorScheduling } from '../../../common/types/connectors'; export const updateConnectorScheduling = async ( client: IScopedClusterClient, connectorId: string, scheduling: ConnectorScheduling ) => { - const connectorResult = await client.asCurrentUser.get({ + const connectorResult = await client.asCurrentUser.get({ id: connectorId, index: CONNECTORS_INDEX, }); const connector = connectorResult._source; if (connector) { - return await client.asCurrentUser.index({ + return await client.asCurrentUser.index({ document: { ...connector, scheduling }, id: connectorId, index: CONNECTORS_INDEX, diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.ts b/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.ts index dfa2558449cdd..a38ea61e9e36e 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.ts @@ -8,7 +8,7 @@ import { IScopedClusterClient } from '@kbn/core/server'; import { CONNECTORS_INDEX } from '../..'; -import { Connector } from '../../types/connector'; +import { ConnectorDocument } from '../../../common/types/connectors'; export const generateApiKey = async (client: IScopedClusterClient, indexName: string) => { const apiKeyResult = await client.asCurrentUser.security.createApiKey({ @@ -25,7 +25,7 @@ export const generateApiKey = async (client: IScopedClusterClient, indexName: st }, }, }); - const connectorResult = await client.asCurrentUser.search({ + const connectorResult = await client.asCurrentUser.search({ index: CONNECTORS_INDEX, query: { term: { 'index_name.keyword': indexName } }, }); diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts index 9e6337211c5e3..8ee32ab55b688 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts @@ -45,7 +45,7 @@ export function registerConnectorRoutes({ router }: RouteDependencies) { validate: { body: schema.recordOf( schema.string(), - schema.object({ label: schema.string(), value: schema.nullable(schema.string()) }) + schema.object({ label: schema.string(), value: schema.string() }) ), params: schema.object({ connectorId: schema.string(), diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.test.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.test.ts index 3891f4023feb0..8dc5a7e3d7081 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.test.ts @@ -10,6 +10,49 @@ import { MockRouter, mockDependencies, mockRequestHandler } from '../../../__moc import { registerCrawlerRoutes } from './crawler'; describe('crawler routes', () => { + describe('POST /internal/enterprise_search/crawler', () => { + let mockRouter: MockRouter; + + beforeEach(() => { + jest.clearAllMocks(); + mockRouter = new MockRouter({ + method: 'post', + path: '/internal/enterprise_search/crawler', + }); + + registerCrawlerRoutes({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('creates a request to enterprise search', () => { + expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ + path: '/api/ent/v1/internal/indices', + }); + }); + + it('validates correctly with name and language', () => { + const request = { body: { index_name: 'index-name', language: 'en' } }; + mockRouter.shouldValidate(request); + }); + + it('validates correctly when language is null', () => { + const request = { body: { index_name: 'index-name', language: null } }; + mockRouter.shouldValidate(request); + }); + + it('fails validation without name', () => { + const request = { body: { language: 'en' } }; + mockRouter.shouldThrow(request); + }); + + it('fails validation without language', () => { + const request = { body: { index_name: 'index-ame' } }; + mockRouter.shouldThrow(request); + }); + }); + describe('GET /internal/enterprise_search/indices/{indexName}/crawler', () => { let mockRouter: MockRouter; @@ -430,7 +473,7 @@ describe('crawler routes', () => { it('creates a request to enterprise search', () => { expect(mockRequestHandler.createRequest).toHaveBeenCalledWith({ - path: '/api/ent/v1/internal/crawler/validate_url', + path: '/api/ent/v1/internal/crawler2/validate_url', }); }); diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts index 652f72318074e..c41916fe20675 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts @@ -22,12 +22,12 @@ export function registerCrawlerRoutes(routeDependencies: RouteDependencies) { validate: { body: schema.object({ index_name: schema.string(), - language: schema.string(), + language: schema.oneOf([schema.string(), schema.literal(null)]), }), }, }, enterpriseSearchRequestHandler.createRequest({ - path: '/api/ent/v1/internal/indices/', + path: '/api/ent/v1/internal/indices', }) ); @@ -42,7 +42,7 @@ export function registerCrawlerRoutes(routeDependencies: RouteDependencies) { }, }, enterpriseSearchRequestHandler.createRequest({ - path: '/api/ent/v1/internal/crawler/validate_url', + path: '/api/ent/v1/internal/crawler2/validate_url', }) ); diff --git a/x-pack/plugins/fleet/common/constants/download_source.ts b/x-pack/plugins/fleet/common/constants/download_source.ts index 22959ed7023bb..76b6f2ce397ab 100644 --- a/x-pack/plugins/fleet/common/constants/download_source.ts +++ b/x-pack/plugins/fleet/common/constants/download_source.ts @@ -5,8 +5,9 @@ * 2.0. */ -// Default URL used to download Elastic Agent -export const DEFAULT_DOWNLOAD_SOURCE = 'https://artifacts.elastic.co'; +// Default source URI used to download Elastic Agent +export const DEFAULT_DOWNLOAD_SOURCE_URI = + 'https://artifacts.elastic.co/downloads/beats/elastic-agent'; export const DOWNLOAD_SOURCE_SAVED_OBJECT_TYPE = 'ingest-download-sources'; diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/download_sources.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/download_sources.yaml index d963e82089303..969f5851294d8 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/download_sources.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/download_sources.yaml @@ -10,7 +10,6 @@ properties: host: type: string required: - - id - is_default - name - host diff --git a/x-pack/plugins/fleet/common/services/routes.ts b/x-pack/plugins/fleet/common/services/routes.ts index 9e6b27703bd2f..faadef1a95c9e 100644 --- a/x-pack/plugins/fleet/common/services/routes.ts +++ b/x-pack/plugins/fleet/common/services/routes.ts @@ -20,6 +20,7 @@ import { APP_API_ROUTES, K8S_API_ROUTES, PRECONFIGURATION_API_ROUTES, + DOWNLOAD_SOURCE_API_ROUTES, } from '../constants'; export const epmRouteService = { @@ -231,3 +232,14 @@ export const enrollmentAPIKeyRouteService = { export const setupRouteService = { getSetupPath: () => SETUP_API_ROUTE, }; + +export const downloadSourceRoutesService = { + getInfoPath: (downloadSourceId: string) => + DOWNLOAD_SOURCE_API_ROUTES.INFO_PATTERN.replace('{sourceId}', downloadSourceId), + getUpdatePath: (downloadSourceId: string) => + DOWNLOAD_SOURCE_API_ROUTES.UPDATE_PATTERN.replace('{sourceId}', downloadSourceId), + getListPath: () => DOWNLOAD_SOURCE_API_ROUTES.LIST_PATTERN, + getDeletePath: (downloadSourceId: string) => + DOWNLOAD_SOURCE_API_ROUTES.DELETE_PATTERN.replace('{sourceId}', downloadSourceId), + getCreatePath: () => DOWNLOAD_SOURCE_API_ROUTES.CREATE_PATTERN, +}; diff --git a/x-pack/plugins/fleet/common/types/models/agent_policy.ts b/x-pack/plugins/fleet/common/types/models/agent_policy.ts index a7b24911d8306..40a6c8cdb9b48 100644 --- a/x-pack/plugins/fleet/common/types/models/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/agent_policy.ts @@ -39,6 +39,7 @@ export interface AgentPolicy extends Omit { updated_at: string; updated_by: string; revision: number; + agents?: number; } export type AgentPolicySOAttributes = Omit; diff --git a/x-pack/plugins/fleet/common/types/models/package_policy.ts b/x-pack/plugins/fleet/common/types/models/package_policy.ts index c865d7ba8a9e7..047bd9a403d9d 100644 --- a/x-pack/plugins/fleet/common/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/package_policy.ts @@ -63,6 +63,7 @@ export interface NewPackagePolicy { description?: string; namespace: string; enabled: boolean; + is_managed?: boolean; policy_id: string; output_id: string; package?: PackagePolicyPackage; diff --git a/x-pack/plugins/fleet/common/types/rest_spec/download_sources.ts b/x-pack/plugins/fleet/common/types/rest_spec/download_sources.ts index 13af84f372c2f..bb66908b3bddd 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/download_sources.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/download_sources.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { DownloadSourceBase } from '../models'; +import type { DownloadSourceBase, DownloadSource } from '../models'; import type { ListResult } from './common'; @@ -28,18 +28,17 @@ export interface PutDownloadSourceRequest { outputId: string; }; body: { - id: string; name: string; - hosts: string; + host: string; is_default?: boolean; }; } export interface PostDownloadSourceRequest { body: { - id: string; + id?: string; name: string; - hosts: string; + host: string; is_default?: boolean; }; } @@ -48,4 +47,4 @@ export interface PutDownloadSourceResponse { item: DownloadSourceBase; } -export type GetDownloadSourceResponse = ListResult; +export type GetDownloadSourceResponse = ListResult; diff --git a/x-pack/plugins/fleet/cypress/cypress.json b/x-pack/plugins/fleet/cypress/cypress.json index 6886e5c245cc0..b36d0c513116c 100644 --- a/x-pack/plugins/fleet/cypress/cypress.json +++ b/x-pack/plugins/fleet/cypress/cypress.json @@ -2,7 +2,7 @@ "baseUrl": "http://localhost:5620", "defaultCommandTimeout": 60000, "requestTimeout": 60000, - "responseTimetout": 60000, + "responseTimeout": 60000, "execTimeout": 120000, "pageLoadTimeout": 120000, "nodeVersion": "system", diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.tsx index 47c2db3db05a9..ba8d0bf5d568f 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiText, EuiSpacer } from '@elastic/eui'; -import { useGetOutputs, useLicense } from '../../../../hooks'; +import { useGetOutputs, useLicense, useGetDownloadSources } from '../../../../hooks'; import { LICENCE_FOR_PER_POLICY_OUTPUT, FLEET_APM_PACKAGE, @@ -20,6 +20,7 @@ import type { NewAgentPolicy, AgentPolicy } from '../../../../types'; // The super select component do not support null or '' as a value export const DEFAULT_OUTPUT_VALUE = '@@##DEFAULT_OUTPUT_VALUE##@@'; +export const DEFAULT_DOWNLOAD_SOURCE_VALUE = '@@##DEFAULT_DOWNLOAD_SOURCE_VALUE##@@'; function getOutputLabel(name: string, disabledMessage?: React.ReactNode) { if (!disabledMessage) { @@ -136,3 +137,54 @@ export function useOutputOptions(agentPolicy: Partial) { + const downloadSourcesRequest = useGetDownloadSources(); + + const dataDownloadSourceOptions = useMemo(() => { + if (downloadSourcesRequest.isLoading || !downloadSourcesRequest.data) { + return []; + } + + const defaultDownloadSource = downloadSourcesRequest.data.items.find((item) => item.is_default); + const defaultDownloadSourceName = defaultDownloadSource?.name; + + return [ + getDefaultDownloadSource(defaultDownloadSourceName), + ...downloadSourcesRequest.data.items + .filter((item) => !item.is_default) + .map((item) => { + return { + value: item.id, + inputDisplay: item.name, + }; + }), + ]; + }, [downloadSourcesRequest]); + + return useMemo( + () => ({ + dataDownloadSourceOptions, + isLoading: downloadSourcesRequest.isLoading, + }), + [dataDownloadSourceOptions, downloadSourcesRequest.isLoading] + ); +} + +function getDefaultDownloadSource( + defaultDownloadSourceName?: string, + defaultDownloadSourceDisabled?: boolean, + defaultDownloadSourceDisabledMessage?: React.ReactNode +) { + return { + inputDisplay: getOutputLabel( + i18n.translate('xpack.fleet.agentPolicy.downloadSourcesOptions.defaultOutputText', { + defaultMessage: 'Default (currently {defaultDownloadSourceName})', + values: { defaultDownloadSourceName }, + }), + defaultDownloadSourceDisabledMessage + ), + value: DEFAULT_DOWNLOAD_SOURCE_VALUE, + disabled: defaultDownloadSourceDisabled, + }; +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.tsx index e1c6bbafa21a7..3662465054c49 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.tsx @@ -33,7 +33,12 @@ import type { ValidationResults } from '../agent_policy_validation'; import { policyHasFleetServer } from '../../../../services'; -import { useOutputOptions, DEFAULT_OUTPUT_VALUE } from './hooks'; +import { + useOutputOptions, + useDownloadSourcesOptions, + DEFAULT_OUTPUT_VALUE, + DEFAULT_DOWNLOAD_SOURCE_VALUE, +} from './hooks'; interface Props { agentPolicy: Partial; @@ -57,6 +62,8 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent = monitoringOutputOptions, isLoading: isLoadingOptions, } = useOutputOptions(agentPolicy); + const { dataDownloadSourceOptions, isLoading: isLoadingDownloadSources } = + useDownloadSourcesOptions(agentPolicy); // agent monitoring checkbox group can appear multiple times in the DOM, ids have to be unique to work correctly const monitoringCheckboxIdSuffix = Date.now(); @@ -361,6 +368,46 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent = /> + + + + } + description={ + + } + > + + { + updateAgentPolicy({ + download_source_id: e !== DEFAULT_DOWNLOAD_SOURCE_VALUE ? e : null, + }); + }} + options={dataDownloadSourceOptions} + data-test-subj="agentPolicyForm.downloadSource.select" + /> + + {isEditing && 'id' in agentPolicy && !agentPolicy.is_managed ? ( = {(deleteAgentPolicyPrompt) => { return ( deleteAgentPolicyPrompt(agentPolicy.id!, onDelete)} > diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_define_package_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_define_package_policy.tsx index 634c173a01111..77b69651143f9 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_define_package_policy.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_define_package_policy.tsx @@ -18,6 +18,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiLink, + EuiCallOut, } from '@elastic/eui'; import styled from 'styled-components'; @@ -159,255 +160,272 @@ export const StepDefinePackagePolicy: React.FunctionComponent<{ isLoadingPackagePolicies, ]); + const isManaged = packagePolicy.is_managed; + return validationResults ? ( - - - - } - description={ - + {isManaged && ( + + } + iconType="lock" /> - } - > - - {/* Name */} - - - } - > - - updatePackagePolicy({ - name: e.target.value, - }) - } - data-test-subj="packagePolicyNameInput" + )} + + - - - - {/* Description */} - - - } - labelAppend={ - + + } + description={ + + } + > + + {/* Name */} + + - - } - isInvalid={!!validationResults.description} - error={validationResults.description} - > - - updatePackagePolicy({ - description: e.target.value, - }) } - data-test-subj="packagePolicyDescriptionInput" - /> - - - - {/* Required vars */} - {requiredVars.map((varDef) => { - const { name: varName, type: varType } = varDef; - if (!packagePolicy.vars || !packagePolicy.vars[varName]) return null; - const value = packagePolicy.vars[varName].value; - - return ( - - { + > + updatePackagePolicy({ - vars: { - ...packagePolicy.vars, - [varName]: { - type: varType, - value: newValue, - }, - }, - }); - }} - errors={validationResults.vars![varName]} - forceShowErrors={submitAttempted} + name: e.target.value, + }) + } + data-test-subj="packagePolicyNameInput" /> - - ); - })} + + - {/* Advanced options toggle */} - {!noAdvancedToggle && ( + {/* Description */} - - - setIsShowingAdvanced(!isShowingAdvanced)} - flush="left" - > + + } + labelAppend={ + - + + } + isInvalid={!!validationResults.description} + error={validationResults.description} + > + + updatePackagePolicy({ + description: e.target.value, + }) + } + data-test-subj="packagePolicyDescriptionInput" + /> + + + + {/* Required vars */} + {requiredVars.map((varDef) => { + const { name: varName, type: varType } = varDef; + if (!packagePolicy.vars || !packagePolicy.vars[varName]) return null; + const value = packagePolicy.vars[varName].value; + + return ( + + { + updatePackagePolicy({ + vars: { + ...packagePolicy.vars, + [varName]: { + type: varType, + value: newValue, + }, + }, + }); + }} + errors={validationResults.vars![varName]} + forceShowErrors={submitAttempted} + /> - {!isShowingAdvanced && !!validationResults.namespace ? ( + ); + })} + + {/* Advanced options toggle */} + {!noAdvancedToggle && !isManaged && ( + + - + setIsShowingAdvanced(!isShowingAdvanced)} + flush="left" + > - + - ) : null} - - - )} + {!isShowingAdvanced && !!validationResults.namespace ? ( + + + + + + ) : null} + + + )} - {/* Advanced options content */} - {/* Todo: Populate list of existing namespaces */} - {isShowingAdvanced ? ( - - - - - } - helpText={ - - {i18n.translate( - 'xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyNamespaceHelpLearnMoreLabel', - { defaultMessage: 'Learn more' } - )} - - ), - }} - /> - } - > - + + + } - onCreateOption={(newNamespace: string) => { - updatePackagePolicy({ - namespace: newNamespace, - }); - }} - onChange={(newNamespaces: Array<{ label: string }>) => { - updatePackagePolicy({ - namespace: newNamespaces.length ? newNamespaces[0].label : '', - }); - }} - /> - - - - - } - helpText={ - - {i18n.translate( - 'xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyDataRetentionLearnMoreLink', - { defaultMessage: 'Learn more' } - )} - - ), + helpText={ + + {i18n.translate( + 'xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyNamespaceHelpLearnMoreLabel', + { defaultMessage: 'Learn more' } + )} + + ), + }} + /> + } + > + { + updatePackagePolicy({ + namespace: newNamespace, + }); }} - /> - } - > -
- - - {/* Advanced vars */} - {advancedVars.map((varDef) => { - const { name: varName, type: varType } = varDef; - if (!packagePolicy.vars || !packagePolicy.vars[varName]) return null; - const value = packagePolicy.vars![varName].value; - return ( - - { + onChange={(newNamespaces: Array<{ label: string }>) => { updatePackagePolicy({ - vars: { - ...packagePolicy.vars, - [varName]: { - type: varType, - value: newValue, - }, - }, + namespace: newNamespaces.length ? newNamespaces[0].label : '', }); }} - errors={validationResults.vars![varName]} - forceShowErrors={submitAttempted} /> - - ); - })} - - - ) : null} - - + + + + + } + helpText={ + + {i18n.translate( + 'xpack.fleet.createPackagePolicy.stepConfigure.packagePolicyDataRetentionLearnMoreLink', + { defaultMessage: 'Learn more' } + )} + + ), + }} + /> + } + > +
+ + + {/* Advanced vars */} + {advancedVars.map((varDef) => { + const { name: varName, type: varType } = varDef; + if (!packagePolicy.vars || !packagePolicy.vars[varName]) return null; + const value = packagePolicy.vars![varName].value; + return ( + + { + updatePackagePolicy({ + vars: { + ...packagePolicy.vars, + [varName]: { + type: varType, + value: newValue, + }, + }, + }); + }} + errors={validationResults.vars![varName]} + forceShowErrors={submitAttempted} + /> + + ); + })} + + + ) : null} + + + ) : ( ); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/settings/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/settings/index.tsx index 13b7135d0c095..87614fc6413c8 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/settings/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/details_page/components/settings/index.tsx @@ -85,6 +85,8 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>( data_output_id, // eslint-disable-next-line @typescript-eslint/naming-convention monitoring_output_id, + // eslint-disable-next-line @typescript-eslint/naming-convention + download_source_id, } = agentPolicy; const { data, error } = await sendUpdateAgentPolicy(agentPolicy.id, { name, @@ -94,6 +96,7 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>( unenroll_timeout, data_output_id, monitoring_output_id, + download_source_id, }); if (data) { notifications.toasts.addSuccess( diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/confirm_update.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/confirm_update.tsx new file mode 100644 index 0000000000000..cdc2e00736333 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/confirm_update.tsx @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import type { DownloadSource } from '../../../../types'; + +import type { useConfirmModal } from '../../hooks/use_confirm_modal'; + +import { getCountsForDownloadSource } from './services/get_count'; + +interface ConfirmDescriptionProps { + downloadSource: DownloadSource; + agentCount: number; + agentPolicyCount: number; +} + +const ConfirmDescription: React.FunctionComponent = ({ + downloadSource, + agentCount, + agentPolicyCount, +}) => ( + {downloadSource.name}, + agents: ( + + + + ), + policies: ( + + + + ), + }} + /> +); + +export async function confirmUpdate( + downloadSource: DownloadSource, + confirm: ReturnType['confirm'] +) { + const { agentCount, agentPolicyCount } = await getCountsForDownloadSource(downloadSource); + return confirm( + , + + ); +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/index.test.tsx new file mode 100644 index 0000000000000..464d0601ced2b --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/index.test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import type { DownloadSource } from '../../../../types'; +import { createFleetTestRendererMock } from '../../../../../../mock'; + +import { EditDownloadSourceFlyout } from '.'; + +jest.mock('../../../../../../hooks/use_fleet_status', () => ({ + FleetStatusProvider: (props: any) => { + return props.children; + }, + useFleetStatus: jest.fn().mockReturnValue({}), +})); + +function renderFlyout(downloadSource?: DownloadSource) { + const renderer = createFleetTestRendererMock(); + + const comp = renderer.render( + {}} /> + ); + + return { comp }; +} +describe('EditOutputFlyout', () => { + it('should render the flyout if there is no download source provided', async () => { + const { comp } = renderFlyout(); + expect(comp.queryByLabelText('Name')).not.toBeNull(); + expect(comp.queryByLabelText('Host')).not.toBeNull(); + expect(comp.queryByPlaceholderText('Specify name')).not.toBeNull(); + expect(comp.queryByPlaceholderText('Specify host')).not.toBeNull(); + }); + + it('should render the flyout if the provided download source is valid', async () => { + const { comp } = renderFlyout({ + name: 'New Host', + host: 'https://test-registry.co/path', + id: 'test-ds-1', + is_default: false, + }); + expect(comp.queryByLabelText('Name')).not.toBeNull(); + expect(comp.queryByLabelText('Host')).not.toBeNull(); + expect(comp.queryByDisplayValue('New Host')).not.toBeNull(); + expect(comp.queryByDisplayValue('https://test-registry.co/path')).not.toBeNull(); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/index.tsx new file mode 100644 index 0000000000000..2ede5f992bc02 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/index.tsx @@ -0,0 +1,179 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutHeader, + EuiTitle, + EuiFlyoutFooter, + EuiFlexGroup, + EuiFlexItem, + EuiButtonEmpty, + EuiButton, + EuiForm, + EuiFormRow, + EuiFieldText, + EuiLink, + EuiSwitch, + EuiSpacer, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import type { DownloadSource } from '../../../../types'; +import { FLYOUT_MAX_WIDTH } from '../../constants'; +import { useBreadcrumbs, useStartServices } from '../../../../hooks'; + +import { useDowloadSourceFlyoutForm } from './use_download_source_flyout_form'; + +export interface EditDownloadSourceFlyoutProps { + downloadSource?: DownloadSource; + onClose: () => void; +} + +export const EditDownloadSourceFlyout: React.FunctionComponent = ({ + onClose, + downloadSource, +}) => { + useBreadcrumbs('settings'); + const form = useDowloadSourceFlyoutForm(onClose, downloadSource); + const inputs = form.inputs; + const { docLinks } = useStartServices(); + + return ( + + + +

+ {!downloadSource ? ( + + ) : ( + + )} +

+
+
+ + + + } + {...inputs.nameInput.formRowProps} + > + + + + + + ), + }} + /> + } + label={ + + } + > + + + + + + } + /> + + + + + + + + + + + + + + + + + +
+ ); +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/services/get_count.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/services/get_count.test.tsx new file mode 100644 index 0000000000000..fb40dcce75945 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/services/get_count.test.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { DownloadSource } from '../../../../../types'; +import { sendGetAgents, sendGetAgentPolicies } from '../../../../../hooks'; + +import { getCountsForDownloadSource } from './get_count'; + +jest.mock('../../../../../hooks', () => ({ + ...jest.requireActual('../../../../../hooks'), + sendGetAgents: jest.fn(), + sendGetAgentPolicies: jest.fn(), +})); + +const mockedSendGetAgents = sendGetAgents as jest.Mock; +const mockedSendGetAgentPolicies = sendGetAgentPolicies as jest.Mock; + +describe('getCountsForDownloadSource', () => { + const downloadSource: DownloadSource = { + name: 'New Host', + host: 'https://test-registry.co/path', + id: 'test-ds-1', + is_default: false, + }; + + beforeEach(async () => { + const mapAgents = (ids: string[]) => + ids.map((agent) => ({ + id: agent, + active: true, + policy_id: 'policy1', + local_metadata: { host: { hostname: agent } }, + })); + mockedSendGetAgents.mockResolvedValueOnce({ + data: { + items: mapAgents(['agent1', 'agent2', 'agent3', 'agent4', 'agent5']), + total: 6, + totalInactive: 0, + }, + }); + + mockedSendGetAgentPolicies.mockResolvedValueOnce({ + data: { + items: [ + { + name: 'Agent policy 1', + namespace: 'default', + description: '', + monitoring_enabled: ['logs', 'metrics'], + download_source_id: 'test-ds-1', + }, + { + name: 'Agent policy 2', + namespace: 'default', + description: '', + monitoring_enabled: ['logs', 'metrics'], + download_source_id: 'test-ds-1', + }, + ], + }, + }); + }); + + it('return agentPolicyCount and agentCount', async () => { + expect(await getCountsForDownloadSource(downloadSource)).toEqual({ + agentCount: 6, + agentPolicyCount: 2, + }); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/services/get_count.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/services/get_count.tsx new file mode 100644 index 0000000000000..ce9428771c0e4 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/services/get_count.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { sendGetAgentPolicies, sendGetAgents } from '../../../../../hooks'; +import type { DownloadSource } from '../../../../../types'; +import { AGENT_POLICY_SAVED_OBJECT_TYPE, SO_SEARCH_LIMIT } from '../../../../../constants'; + +export async function getCountsForDownloadSource(downloadSource: DownloadSource) { + let kuery = `${AGENT_POLICY_SAVED_OBJECT_TYPE}.download_source_id:"${downloadSource.id}"`; + if (downloadSource.is_default) { + kuery += ` or (not ${AGENT_POLICY_SAVED_OBJECT_TYPE}.download_source_id:*)`; + } + const agentPolicies = await sendGetAgentPolicies({ + kuery, + page: 1, + perPage: SO_SEARCH_LIMIT, + }); + + if (agentPolicies.error) { + throw agentPolicies.error; + } + const agentPolicyCount = agentPolicies.data?.items?.length ?? 0; + + let agentCount = 0; + if (agentPolicyCount > 0) { + const agents = await sendGetAgents({ + page: 1, + perPage: 0, + showInactive: false, + kuery: agentPolicies.data?.items.map((policy) => `policy_id:"${policy.id}"`).join(' or '), + }); + + if (agents.error) { + throw agents.error; + } + + agentCount = agents.data?.total ?? 0; + } + + return { agentPolicyCount, agentCount }; +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_delete_download_source.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_delete_download_source.tsx new file mode 100644 index 0000000000000..ecd3130499572 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_delete_download_source.tsx @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback } from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; + +import { sendDeleteDownloadSource, useStartServices } from '../../../../hooks'; +import type { DownloadSource } from '../../../../types'; + +import { useConfirmModal } from '../../hooks/use_confirm_modal'; + +import { getCountsForDownloadSource } from './services/get_count'; + +const ConfirmTitle = () => ( + +); + +interface ConfirmDeleteDescriptionProps { + downloadSource: DownloadSource; + agentCount: number; + agentPolicyCount: number; +} + +const ConfirmDeleteDescription: React.FunctionComponent = ({ + downloadSource, + agentCount, + agentPolicyCount, +}) => ( + {downloadSource.name}, + agents: ( + + + + ), + policies: ( + + + + ), + }} + /> +); + +export function useDeleteDownloadSource(onSuccess: () => void) { + const { confirm } = useConfirmModal(); + const { notifications } = useStartServices(); + const deleteDownloadSource = useCallback( + async (downloadSource: DownloadSource) => { + try { + const { agentCount, agentPolicyCount } = await getCountsForDownloadSource(downloadSource); + + const isConfirmed = await confirm( + , + , + { + buttonColor: 'danger', + confirmButtonText: i18n.translate( + 'xpack.fleet.settings.deleteDownloadSource.confirmButtonLabel', + { + defaultMessage: 'Delete and deploy', + } + ), + } + ); + + if (!isConfirmed) { + return; + } + + const res = await sendDeleteDownloadSource(downloadSource.id); + + if (res.error) { + throw res.error; + } + + onSuccess(); + } catch (err) { + notifications.toasts.addError(err, { + title: i18n.translate('xpack.fleet.settings.deleteDownloadSource.errorToastTitle', { + defaultMessage: 'Error deleting agent binary source.', + }), + }); + } + }, + [confirm, notifications.toasts, onSuccess] + ); + + return { deleteDownloadSource }; +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_download_source_flyout_form.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_download_source_flyout_form.test.tsx new file mode 100644 index 0000000000000..25136b0cb16db --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_download_source_flyout_form.test.tsx @@ -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 { validateHost } from './use_download_source_flyout_form'; + +describe('Download source form validation', () => { + describe('validateHost', () => { + it('should not work without any urls', () => { + const res = validateHost(''); + + expect(res).toEqual(['Host is required']); + }); + + it('should work with valid url with https protocol', () => { + const res = validateHost('https://test.co:9200'); + + expect(res).toBeUndefined(); + }); + + it('should work with valid url with http protocol', () => { + const res = validateHost('http://test.co'); + + expect(res).toBeUndefined(); + }); + + it('should work with valid url with path', () => { + const res = validateHost('http://test.co/download'); + + expect(res).toBeUndefined(); + }); + + it('should return an error with invalid url', () => { + const res = validateHost('toto'); + + expect(res).toEqual(['Invalid URL']); + }); + + it('should return an error with url with invalid port', () => { + const res = validateHost('https://test.fr:qwerty9200'); + + expect(res).toEqual(['Invalid URL']); + }); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_download_source_flyout_form.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_download_source_flyout_form.tsx new file mode 100644 index 0000000000000..ea965646cd6be --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_flyout/use_download_source_flyout_form.tsx @@ -0,0 +1,144 @@ +/* + * Copyright 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'; + +import { i18n } from '@kbn/i18n'; + +import { + sendPostDownloadSource, + useInput, + useSwitchInput, + useStartServices, + sendPutDownloadSource, +} from '../../../../hooks'; +import type { DownloadSource, PostDownloadSourceRequest } from '../../../../types'; +import { useConfirmModal } from '../../hooks/use_confirm_modal'; + +import { confirmUpdate } from './confirm_update'; + +export function useDowloadSourceFlyoutForm(onSuccess: () => void, downloadSource?: DownloadSource) { + const [isLoading, setIsloading] = useState(false); + const { notifications } = useStartServices(); + const { confirm } = useConfirmModal(); + + const nameInput = useInput(downloadSource?.name ?? '', validateName); + + const defaultDownloadSourceInput = useSwitchInput( + downloadSource?.is_default ?? false, + downloadSource?.is_default + ); + + const hostInput = useInput(downloadSource?.host ?? '', validateHost); + + const inputs = { + nameInput, + hostInput, + defaultDownloadSourceInput, + }; + + const hasChanged = Object.values(inputs).some((input) => input.hasChanged); + + const validate = useCallback(() => { + const nameInputValid = nameInput.validate(); + const hostValid = hostInput.validate(); + + return nameInputValid && hostValid; + }, [nameInput, hostInput]); + + const submit = useCallback(async () => { + try { + if (!validate()) { + return; + } + setIsloading(true); + + const data: PostDownloadSourceRequest['body'] = { + name: nameInput.value, + host: hostInput.value, + is_default: defaultDownloadSourceInput.value, + }; + + if (downloadSource) { + // Update + if (!(await confirmUpdate(downloadSource, confirm))) { + setIsloading(false); + return; + } + + const res = await sendPutDownloadSource(downloadSource.id, data); + if (res.error) { + throw res.error; + } + } else { + // Create + const res = await sendPostDownloadSource(data); + if (res.error) { + throw res.error; + } + } + + onSuccess(); + setIsloading(false); + } catch (err) { + setIsloading(false); + notifications.toasts.addError(err, { + title: i18n.translate('xpack.fleet.settings.dowloadSourceFlyoutForm.errorToastTitle', { + defaultMessage: 'Error while saving binary source', + }), + }); + } + }, [ + confirm, + defaultDownloadSourceInput.value, + downloadSource, + hostInput.value, + nameInput.value, + notifications.toasts, + onSuccess, + validate, + ]); + + return { + inputs, + submit, + isLoading, + isDisabled: isLoading || (downloadSource && !hasChanged), + }; +} + +function validateName(value: string) { + if (!value || value === '') { + return [ + i18n.translate('xpack.fleet.settings.dowloadSourceFlyoutForm.nameIsRequiredErrorMessage', { + defaultMessage: 'Name is required', + }), + ]; + } +} + +export function validateHost(value: string) { + try { + if (!value || value === '') { + return [ + i18n.translate('xpack.fleet.settings.dowloadSourceFlyoutForm.HostIsRequiredErrorMessage', { + defaultMessage: 'Host is required', + }), + ]; + } + const urlParsed = new URL(value); + if (!['http:', 'https:'].includes(urlParsed.protocol)) { + throw new Error('Invalid protocol'); + } + } catch (error) { + return [ + i18n.translate('xpack.fleet.settings.dowloadSourceFlyoutForm.hostError', { + defaultMessage: 'Invalid URL', + }), + ]; + } +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_table/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_table/index.tsx new file mode 100644 index 0000000000000..87034bf900fda --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/download_source_table/index.tsx @@ -0,0 +1,140 @@ +/* + * Copyright 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 styled from 'styled-components'; +import { EuiBasicTable, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiCheckbox } from '@elastic/eui'; +import type { EuiBasicTableColumn } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { useLink } from '../../../../hooks'; +import type { DownloadSource } from '../../../../types'; + +export interface DownloadSourceTableProps { + downloadSources: DownloadSource[]; + deleteDownloadSource: (ds: DownloadSource) => void; +} + +const NameFlexItemWithMaxWidth = styled(EuiFlexItem)` + max-width: 250px; +`; + +// Allow child to be truncated +const FlexGroupWithMinWidth = styled(EuiFlexGroup)` + min-width: 0px; +`; + +export const DownloadSourceTable: React.FunctionComponent = ({ + downloadSources, + deleteDownloadSource, +}) => { + const { getHref } = useLink(); + + const columns = useMemo((): Array> => { + return [ + { + render: (downloadSource: DownloadSource) => ( + + +

+ {downloadSource.name} +

+
+
+ ), + width: '288px', + name: i18n.translate('xpack.fleet.settings.downloadSourcesTable.nameColumnTitle', { + defaultMessage: 'Name', + }), + }, + { + truncateText: true, + render: (downloadSource: DownloadSource) => ( + + +

+ {downloadSource.host} +

+
+
+ ), + name: i18n.translate('xpack.fleet.settings.downloadSourcesTable.hostColumnTitle', { + defaultMessage: 'Host', + }), + }, + { + render: (downloadSource: DownloadSource) => ( + undefined} + /> + ), + width: '200px', + name: i18n.translate('xpack.fleet.settings.downloadSourcesTable.defaultColumnTitle', { + defaultMessage: 'Default', + }), + }, + { + width: '68px', + render: (downloadSource: DownloadSource) => { + const isDeleteVisible = !downloadSource.is_default; + + return ( + + + {isDeleteVisible && ( + deleteDownloadSource(downloadSource)} + title={i18n.translate( + 'xpack.fleet.settings.downloadSourceSection.deleteButtonTitle', + { + defaultMessage: 'Delete', + } + )} + data-test-subj="editDownloadSourceTable.delete.btn" + /> + )} + + + + + + ); + }, + name: i18n.translate('xpack.fleet.settings.downloadSourceSection.actionsColumnTitle', { + defaultMessage: 'Actions', + }), + }, + ]; + }, [deleteDownloadSource, getHref]); + + return ; +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/settings_page/agent_binary_section.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/settings_page/agent_binary_section.tsx new file mode 100644 index 0000000000000..ae9a42a7b2144 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/settings_page/agent_binary_section.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiTitle, EuiText, EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import { useLink } from '../../../../hooks'; +import type { DownloadSource } from '../../../../types'; +import { DownloadSourceTable } from '../download_source_table'; + +export interface AgentBinarySectionProps { + downloadSources: DownloadSource[]; + deleteDownloadSource: (ds: DownloadSource) => void; +} + +export const AgentBinarySection: React.FunctionComponent = ({ + downloadSources, + deleteDownloadSource, +}) => { + const { getHref } = useLink(); + + return ( + <> + +

+ +

+
+ + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/settings_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/settings_page/index.tsx index 7749e3304a6ea..4c5db21725639 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/settings_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/settings_page/index.tsx @@ -8,21 +8,26 @@ import React from 'react'; import { EuiSpacer } from '@elastic/eui'; -import type { Output, Settings } from '../../../../types'; +import type { Output, Settings, DownloadSource } from '../../../../types'; import { SettingsSection } from './settings_section'; import { OutputSection } from './output_section'; +import { AgentBinarySection } from './agent_binary_section'; export interface SettingsPageProps { settings: Settings; outputs: Output[]; deleteOutput: (output: Output) => void; + downloadSources: DownloadSource[]; + deleteDownloadSource: (ds: DownloadSource) => void; } export const SettingsPage: React.FunctionComponent = ({ settings, outputs, deleteOutput, + downloadSources, + deleteDownloadSource, }) => { return ( <> @@ -30,6 +35,11 @@ export const SettingsPage: React.FunctionComponent = ({ + + ); }; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/index.tsx index c586e88261940..7a94d9ef4bc79 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/index.tsx @@ -9,7 +9,7 @@ import React, { useCallback } from 'react'; import { EuiPortal } from '@elastic/eui'; import { Router, Route, Switch, useHistory, Redirect } from 'react-router-dom'; -import { useBreadcrumbs, useGetOutputs, useGetSettings } from '../../hooks'; +import { useBreadcrumbs, useGetOutputs, useGetSettings, useGetDownloadSources } from '../../hooks'; import { FLEET_ROUTING_PATHS, pagePathGetters } from '../../constants'; import { DefaultLayout } from '../../layouts'; import { Loading } from '../../components'; @@ -19,6 +19,8 @@ import { withConfirmModalProvider } from './hooks/use_confirm_modal'; import { FleetServerHostsFlyout } from './components/fleet_server_hosts_flyout'; import { EditOutputFlyout } from './components/edit_output_flyout'; import { useDeleteOutput } from './hooks/use_delete_output'; +import { EditDownloadSourceFlyout } from './components/download_source_flyout'; +import { useDeleteDownloadSource } from './components/download_source_flyout/use_delete_download_source'; export const SettingsApp = withConfirmModalProvider(() => { useBreadcrumbs('settings'); @@ -26,23 +28,29 @@ export const SettingsApp = withConfirmModalProvider(() => { const settings = useGetSettings(); const outputs = useGetOutputs(); + const downloadSources = useGetDownloadSources(); const { deleteOutput } = useDeleteOutput(outputs.resendRequest); + const { deleteDownloadSource } = useDeleteDownloadSource(downloadSources.resendRequest); const resendSettingsRequest = settings.resendRequest; const resendOutputRequest = outputs.resendRequest; + const resendDownloadSourceRequest = downloadSources.resendRequest; const onCloseCallback = useCallback(() => { resendSettingsRequest(); resendOutputRequest(); + resendDownloadSourceRequest(); history.replace(pagePathGetters.settings()[1]); - }, [history, resendSettingsRequest, resendOutputRequest]); + }, [resendSettingsRequest, resendOutputRequest, resendDownloadSourceRequest, history]); if ( (settings.isLoading && settings.isInitialRequest) || !settings.data?.item || (outputs.isLoading && outputs.isInitialRequest) || - !outputs.data?.items + !outputs.data?.items || + (downloadSources.isLoading && downloadSources.isInitialRequest) || + !downloadSources.data?.items ) { return ( @@ -71,7 +79,6 @@ export const SettingsApp = withConfirmModalProvider(() => { {(route: { match: { params: { outputId: string } } }) => { const output = outputs.data?.items.find((o) => route.match.params.outputId === o.id); - if (!output) { return ; } @@ -83,12 +90,38 @@ export const SettingsApp = withConfirmModalProvider(() => { ); }} + + + + + + + {(route: { match: { params: { downloadSourceId: string } } }) => { + const downloadSource = downloadSources.data?.items.find( + (o) => route.match.params.downloadSourceId === o.id + ); + if (!downloadSource) { + return ; + } + + return ( + + + + ); + }} + ); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/available_packages.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/available_packages.tsx index af3faff04243d..e8d4692f2a3b9 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/available_packages.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/available_packages.tsx @@ -340,7 +340,7 @@ export const AvailablePackages: React.FC<{ })} description={i18n.translate('xpack.fleet.featuredObsDesc', { defaultMessage: - 'Monitor, detect and diagnose complex performance issues from your application.', + 'Monitor, detect, and diagnose complex application performance issues.', })} href={addBasePath('/app/home#/tutorial/apm')} icon={} diff --git a/x-pack/plugins/fleet/public/components/context_menu_actions.tsx b/x-pack/plugins/fleet/public/components/context_menu_actions.tsx index 5bfb12f865388..53ca16a366f54 100644 --- a/x-pack/plugins/fleet/public/components/context_menu_actions.tsx +++ b/x-pack/plugins/fleet/public/components/context_menu_actions.tsx @@ -13,6 +13,7 @@ import { EuiContextMenuPanel, EuiPopover, EuiButton, + EuiToolTip, } from '@elastic/eui'; import type { EuiButtonProps } from '@elastic/eui/src/components/button/button'; import type { EuiContextMenuProps } from '@elastic/eui/src/components/context_menu/context_menu'; @@ -24,6 +25,7 @@ type Props = { children: JSX.Element; }; isOpen?: boolean; + isManaged?: boolean; onChange?: (isOpen: boolean) => void; } & ( | { @@ -51,24 +53,37 @@ export const ContextMenuActions = React.memo(({ button, onChange, isOpen, } }, [isOpenState, onChange, isOpen]); + const actionButton = button ? ( + + {button.children} + + ) : ( + + ); + return ( - {button.children} - - ) : ( - + > + {actionButton} + + ) : ( + actionButton ) } isOpen={isOpen === undefined ? isOpenState : isOpen} diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx index 42b907cc282f4..9ba89394896ad 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.tsx @@ -37,6 +37,8 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ const refreshAgentPolicy = useAgentPolicyRefresh(); const [isActionsMenuOpen, setIsActionsMenuOpen] = useState(defaultIsOpen); + const isManaged = Boolean(packagePolicy.is_managed); + const onEnrollmentFlyoutClose = useMemo(() => { return () => setIsEnrollmentFlyoutOpen(false); }, []); @@ -148,6 +150,7 @@ export const PackagePolicyActionsMenu: React.FunctionComponent<{ )} setIsActionsMenuOpen(open)} diff --git a/x-pack/plugins/fleet/public/constants/page_paths.ts b/x-pack/plugins/fleet/public/constants/page_paths.ts index e7134f8549e27..479110f2f0142 100644 --- a/x-pack/plugins/fleet/public/constants/page_paths.ts +++ b/x-pack/plugins/fleet/public/constants/page_paths.ts @@ -18,6 +18,7 @@ export type StaticPage = | 'settings' | 'settings_edit_fleet_server_hosts' | 'settings_create_outputs' + | 'settings_create_download_sources' | 'debug'; export type DynamicPage = @@ -38,7 +39,8 @@ export type DynamicPage = | 'agent_list' | 'agent_details' | 'agent_details_logs' - | 'settings_edit_outputs'; + | 'settings_edit_outputs' + | 'settings_edit_download_sources'; export type Page = StaticPage | DynamicPage; @@ -68,6 +70,8 @@ export const FLEET_ROUTING_PATHS = { settings_edit_fleet_server_hosts: '/settings/edit-fleet-server-hosts', settings_create_outputs: '/settings/create-outputs', settings_edit_outputs: '/settings/outputs/:outputId', + settings_create_download_sources: '/settings/create-download-sources', + settings_edit_download_sources: '/settings/downloadSources/:downloadSourceId', debug: '/_debug', // TODO: Move this to the integrations app @@ -191,6 +195,17 @@ export const pagePathGetters: { FLEET_BASE_PATH, FLEET_ROUTING_PATHS.settings_edit_outputs.replace(':outputId', outputId as string), ], + settings_edit_download_sources: ({ downloadSourceId }) => [ + FLEET_BASE_PATH, + FLEET_ROUTING_PATHS.settings_edit_download_sources.replace( + ':downloadSourceId', + downloadSourceId as string + ), + ], settings_create_outputs: () => [FLEET_BASE_PATH, FLEET_ROUTING_PATHS.settings_create_outputs], + settings_create_download_sources: () => [ + FLEET_BASE_PATH, + FLEET_ROUTING_PATHS.settings_create_download_sources, + ], debug: () => [FLEET_BASE_PATH, FLEET_ROUTING_PATHS.debug], }; diff --git a/x-pack/plugins/fleet/public/hooks/use_request/download_source.ts b/x-pack/plugins/fleet/public/hooks/use_request/download_source.ts new file mode 100644 index 0000000000000..2b213501170e1 --- /dev/null +++ b/x-pack/plugins/fleet/public/hooks/use_request/download_source.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { downloadSourceRoutesService } from '../../services'; +import type { + GetDownloadSourceResponse, + PostDownloadSourceRequest, + PutDownloadSourceRequest, +} from '../../types'; + +import { useRequest, sendRequest } from './use_request'; + +export function useGetDownloadSources() { + return useRequest({ + method: 'get', + path: downloadSourceRoutesService.getListPath(), + }); +} + +export function useDefaultDownloadSource() { + const downloadSourcesRequest = useGetDownloadSources(); + const downloadSource = downloadSourcesRequest.data?.items.find((o) => o.is_default); + + return { downloadSource, refresh: downloadSourcesRequest.resendRequest }; +} + +export function sendPutDownloadSource( + downloadSourceId: string, + body: PutDownloadSourceRequest['body'] +) { + return sendRequest({ + method: 'put', + path: downloadSourceRoutesService.getUpdatePath(downloadSourceId), + body, + }); +} + +export function sendPostDownloadSource(body: PostDownloadSourceRequest['body']) { + return sendRequest({ + method: 'post', + path: downloadSourceRoutesService.getCreatePath(), + body, + }); +} + +export function sendDeleteDownloadSource(downloadSourceId: string) { + return sendRequest({ + method: 'delete', + path: downloadSourceRoutesService.getDeletePath(downloadSourceId), + }); +} diff --git a/x-pack/plugins/fleet/public/hooks/use_request/index.ts b/x-pack/plugins/fleet/public/hooks/use_request/index.ts index 2f700052acd7b..1ca5297cb22a2 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/index.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/index.ts @@ -17,3 +17,4 @@ export * from './settings'; export * from './setup'; export * from './app'; export * from './ingest_pipelines'; +export * from './download_source'; diff --git a/x-pack/plugins/fleet/public/services/index.ts b/x-pack/plugins/fleet/public/services/index.ts index 094fe2b66c6c9..b7760134172a9 100644 --- a/x-pack/plugins/fleet/public/services/index.ts +++ b/x-pack/plugins/fleet/public/services/index.ts @@ -40,6 +40,7 @@ export { validationHasErrors, countValidationErrors, getStreamsForInputType, + downloadSourceRoutesService, } from '../../common'; export * from './package_verification'; export * from './pkg_key_from_package_info'; diff --git a/x-pack/plugins/fleet/public/types/index.ts b/x-pack/plugins/fleet/public/types/index.ts index 2cd27e81be9d8..3b02839957b33 100644 --- a/x-pack/plugins/fleet/public/types/index.ts +++ b/x-pack/plugins/fleet/public/types/index.ts @@ -23,6 +23,7 @@ export type { PackagePolicyConfigRecordEntry, PackagePolicyPackage, Output, + DownloadSource, DataStream, Settings, CurrentUpgrade, @@ -121,6 +122,9 @@ export type { PackageSpecCategory, UpdatePackageRequest, UpdatePackageResponse, + GetDownloadSourceResponse, + PostDownloadSourceRequest, + PutDownloadSourceRequest, } from '../../common'; export { entries, ElasticsearchAssetType, KibanaAssetType, InstallStatus } from '../../common'; diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index 3123f2910ed54..b86b636059152 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -61,7 +61,7 @@ export { USER_SETTINGS_TEMPLATE_SUFFIX, PACKAGE_TEMPLATE_SUFFIX, // Download sources - DEFAULT_DOWNLOAD_SOURCE, + DEFAULT_DOWNLOAD_SOURCE_URI, DOWNLOAD_SOURCE_SAVED_OBJECT_TYPE, DEFAULT_DOWNLOAD_SOURCE_ID, } from '../../common'; diff --git a/x-pack/plugins/fleet/server/errors/index.ts b/x-pack/plugins/fleet/server/errors/index.ts index ecd5bb8c670ae..9753f8006566f 100644 --- a/x-pack/plugins/fleet/server/errors/index.ts +++ b/x-pack/plugins/fleet/server/errors/index.ts @@ -62,6 +62,13 @@ export class HostedAgentPolicyRestrictionRelatedError extends IngestManagerError ); } } +export class PackagePolicyRestrictionRelatedError extends IngestManagerError { + constructor(message = 'Cannot perform that action') { + super( + `${message} in Fleet because the package policy is managed by an external orchestration solution, such as Elastic Cloud, Kubernetes, etc. Please make changes using your orchestration solution.` + ); + } +} export class FleetEncryptedSavedObjectEncryptionKeyRequired extends IngestManagerError {} export class FleetSetupError extends IngestManagerError {} export class GenerateServiceTokenError extends IngestManagerError {} diff --git a/x-pack/plugins/fleet/server/integration_tests/__snapshots__/cloud_preconfiguration.test.ts.snap b/x-pack/plugins/fleet/server/integration_tests/__snapshots__/cloud_preconfiguration.test.ts.snap index fc2ce4eb7145e..ff918248ffb57 100644 --- a/x-pack/plugins/fleet/server/integration_tests/__snapshots__/cloud_preconfiguration.test.ts.snap +++ b/x-pack/plugins/fleet/server/integration_tests/__snapshots__/cloud_preconfiguration.test.ts.snap @@ -4,7 +4,7 @@ exports[`Fleet preconfiguration reset Preconfigured cloud policy With a full pre Object { "agent": Object { "download": Object { - "source_uri": "https://artifacts.elastic.co", + "source_uri": "https://artifacts.elastic.co/downloads/beats/elastic-agent", }, "monitoring": Object { "enabled": false, diff --git a/x-pack/plugins/fleet/server/routes/agent/handlers.ts b/x-pack/plugins/fleet/server/routes/agent/handlers.ts index 8f5797d0d3cf3..7a10a50e2fb7b 100644 --- a/x-pack/plugins/fleet/server/routes/agent/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent/handlers.ts @@ -29,7 +29,6 @@ import type { PostBulkUpdateAgentTagsRequestSchema, } from '../../types'; import { defaultIngestErrorHandler } from '../../errors'; -import { licenseService } from '../../services'; import * as AgentService from '../../services/agents'; export const getAgentHandler: RequestHandler< @@ -214,13 +213,6 @@ export const postBulkAgentsReassignHandler: RequestHandler< undefined, TypeOf > = async (context, request, response) => { - if (!licenseService.isGoldPlus()) { - return response.customError({ - statusCode: 403, - body: { message: 'Requires Gold license' }, - }); - } - const coreContext = await context.core; const soClient = coreContext.savedObjects.client; const esClient = coreContext.elasticsearch.client.asInternalUser; diff --git a/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts b/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts index 257112dc6872d..b6e398d269a6f 100644 --- a/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts @@ -16,7 +16,6 @@ import type { PostAgentUnenrollRequestSchema, PostBulkAgentUnenrollRequestSchema, } from '../../types'; -import { licenseService } from '../../services'; import * as AgentService from '../../services/agents'; import { defaultIngestErrorHandler } from '../../errors'; @@ -46,13 +45,6 @@ export const postBulkAgentsUnenrollHandler: RequestHandler< undefined, TypeOf > = async (context, request, response) => { - if (!licenseService.isGoldPlus()) { - return response.customError({ - statusCode: 403, - body: { message: 'Requires Gold license' }, - }); - } - const coreContext = await context.core; const soClient = coreContext.savedObjects.client; const esClient = coreContext.elasticsearch.client.asInternalUser; diff --git a/x-pack/plugins/fleet/server/routes/data_streams/get_data_streams_query_metadata.ts b/x-pack/plugins/fleet/server/routes/data_streams/get_data_streams_query_metadata.ts index 44a77a511ca4c..05f7989d8baea 100644 --- a/x-pack/plugins/fleet/server/routes/data_streams/get_data_streams_query_metadata.ts +++ b/x-pack/plugins/fleet/server/routes/data_streams/get_data_streams_query_metadata.ts @@ -24,9 +24,22 @@ export async function getDataStreamsQueryMetadata({ esClient.search({ size: 1, index: dataStreamName, - sort: 'event.ingested:desc', _source: false, fields: ['event.ingested'], + // We need to use `body` to control the `sort` value here, because otherwise + // it's just appended as a query string to the search operation and we can't + // set `unmapped_type` for cases where `event.ingested` is not defiend, e.g. + // in custom logs or custom HTTPJSON integrations + body: { + sort: { + 'event.ingested': { + order: 'desc', + // Necessary because of https://github.com/elastic/elasticsearch/issues/81960 + missing: 0, + unmapped_type: 'long', + }, + }, + }, }), esClient.termsEnum({ index: dataStreamName, diff --git a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts index f68c8d287472e..f0a5471832de8 100644 --- a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts @@ -190,7 +190,7 @@ export const getListHandler: RequestHandler = async (context, request, response) }); // Return final data streams objects sorted by last activity, descending - // After filtering out data streams that are missing dataset/namespace/type fields + // After filtering out data streams that are missing dataset/namespace/type/package fields body.data_streams = (await Promise.all(dataStreamPromises)) .filter(({ dataset, namespace, type }) => dataset && namespace && type) .sort((a, b) => b.last_activity_ms - a.last_activity_ms); diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index 55b57dc857a90..6512b1a5b0cb8 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -145,6 +145,7 @@ const getSavedObjectTypes = ( description: { type: 'text' }, namespace: { type: 'keyword' }, enabled: { type: 'boolean' }, + is_managed: { type: 'boolean' }, policy_id: { type: 'keyword' }, output_id: { type: 'keyword' }, package: { diff --git a/x-pack/plugins/fleet/server/services/download_source.ts b/x-pack/plugins/fleet/server/services/download_source.ts index c189ac1a23019..7a6df1d67a7f8 100644 --- a/x-pack/plugins/fleet/server/services/download_source.ts +++ b/x-pack/plugins/fleet/server/services/download_source.ts @@ -8,7 +8,7 @@ import type { SavedObjectsClientContract, SavedObject } from '@kbn/core/server'; import { DOWNLOAD_SOURCE_SAVED_OBJECT_TYPE, - DEFAULT_DOWNLOAD_SOURCE, + DEFAULT_DOWNLOAD_SOURCE_URI, DEFAULT_DOWNLOAD_SOURCE_ID, } from '../constants'; @@ -151,9 +151,9 @@ class DownloadSourceService { if (!defaultDS) { const newDefaultDS: DownloadSourceBase = { - name: 'default', + name: 'Elastic Artifacts', is_default: true, - host: DEFAULT_DOWNLOAD_SOURCE, + host: DEFAULT_DOWNLOAD_SOURCE_URI, }; return await this.create(soClient, newDefaultDS, { diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 04abb2f54228e..79d5b69ae14cc 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -53,6 +53,7 @@ import { ingestErrorToResponseOptions, PackagePolicyIneligibleForUpgradeError, PackagePolicyValidationError, + PackagePolicyRestrictionRelatedError, } from '../errors'; import { NewPackagePolicySchema, PackagePolicySchema, UpdatePackagePolicySchema } from '../types'; import type { @@ -380,6 +381,10 @@ class PackagePolicyService implements PackagePolicyServiceInterface { const oldPackagePolicy = await this.get(soClient, id); const { version, ...restOfPackagePolicy } = packagePolicy; + if (packagePolicyUpdate.is_managed && !options?.force) { + throw new PackagePolicyRestrictionRelatedError(`Cannot update package policy ${id}`); + } + if (!oldPackagePolicy) { throw new Error('Package policy not found'); } @@ -481,6 +486,11 @@ class PackagePolicyService implements PackagePolicyServiceInterface { if (!packagePolicy) { throw new Error('Package policy not found'); } + + if (packagePolicy.is_managed && !options?.force) { + throw new PackagePolicyRestrictionRelatedError(`Cannot delete package policy ${id}`); + } + if (!options?.skipUnassignFromAgentPolicies) { await agentPolicyService.unassignPackagePolicies( soClient, @@ -605,7 +615,7 @@ class PackagePolicyService implements PackagePolicyServiceInterface { soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, ids: string[], - options?: { user?: AuthenticatedUser }, + options?: { user?: AuthenticatedUser; force?: boolean }, packagePolicy?: PackagePolicy, pkgVersion?: string ): Promise { @@ -621,6 +631,10 @@ class PackagePolicyService implements PackagePolicyServiceInterface { pkgVersion )); + if (packagePolicy.is_managed && !options?.force) { + throw new PackagePolicyRestrictionRelatedError(`Cannot upgrade package policy ${id}`); + } + await this.doUpgrade(soClient, esClient, id, packagePolicy!, result, packageInfo, options); } catch (error) { result.push({ diff --git a/x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.test.ts b/x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.test.ts index 7f5a894a32e53..13d6803f1ccdf 100644 --- a/x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.test.ts +++ b/x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.test.ts @@ -153,6 +153,7 @@ describe('mapToResults', () => { management: { defaultSearchField: 'excerpt', getInAppUrl: (obj) => ({ path: `/type-c/${obj.id}`, uiCapabilitiesPath: 'test.typeC' }), + getTitle: (obj) => `${obj.attributes.title} ${obj.attributes.name}`, }, }) ); @@ -204,6 +205,7 @@ describe('mapToResults', () => { { excerpt: 'titleC', title: 'foo', + name: 'name', }, [ { name: 'tag A', type: 'tag', id: '1' }, @@ -235,7 +237,7 @@ describe('mapToResults', () => { }, { id: 'resultC', - title: 'titleC', + title: 'foo name', type: 'typeC', url: '/type-c/resultC', score: 42, diff --git a/x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.ts b/x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.ts index 676c92fba0b4c..bc993129435cb 100644 --- a/x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.ts +++ b/x-pack/plugins/global_search_providers/server/providers/saved_objects/map_object_to_result.ts @@ -41,7 +41,7 @@ export const mapToResult = ( object: SavedObjectsFindResult, type: SavedObjectsType ): GlobalSearchProviderResult => { - const { defaultSearchField, getInAppUrl } = type.management ?? {}; + const { defaultSearchField, getInAppUrl, getTitle } = type.management ?? {}; if (defaultSearchField === undefined || getInAppUrl === undefined) { throw new Error('Trying to map an object from a type without management metadata'); } @@ -49,7 +49,7 @@ export const mapToResult = ( id: object.id, // defaultSearchField is dynamic and not 'directly' bound to the generic type of the SavedObject // so we are forced to cast the attributes to any to access the properties associated with it. - title: (object.attributes as any)[defaultSearchField], + title: getTitle ? getTitle(object) : (object.attributes as any)[defaultSearchField], type: object.type, icon: type.management?.icon ?? undefined, url: getInAppUrl(object).path, diff --git a/x-pack/plugins/kubernetes_security/common/constants.ts b/x-pack/plugins/kubernetes_security/common/constants.ts index 625946b99a123..f61633fabc14f 100644 --- a/x-pack/plugins/kubernetes_security/common/constants.ts +++ b/x-pack/plugins/kubernetes_security/common/constants.ts @@ -20,6 +20,8 @@ export const AGGREGATE_MAX_BUCKETS = 2000; // react-query caching keys export const QUERY_KEY_PERCENT_WIDGET = 'kubernetesSecurityPercentWidget'; export const QUERY_KEY_COUNT_WIDGET = 'kubernetesSecurityCountWidget'; +export const QUERY_KEY_CONTAINER_NAME_WIDGET = 'kubernetesSecurityContainerNameWidget'; +export const QUERY_KEY_PROCESS_EVENTS = 'kubernetesSecurityProcessEvents'; export const DEFAULT_QUERY = '{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}'; diff --git a/x-pack/plugins/kubernetes_security/common/translations.ts b/x-pack/plugins/kubernetes_security/common/translations.ts index d13bf8be60265..7d447d3650a06 100644 --- a/x-pack/plugins/kubernetes_security/common/translations.ts +++ b/x-pack/plugins/kubernetes_security/common/translations.ts @@ -22,12 +22,45 @@ export const SEARCH_GROUP_SORT_BY = i18n.translate('xpack.kubernetesSecurity.sea defaultMessage: 'Sort by', }); -export const WIDGET_TOGGLE_SHOW = i18n.translate('xpack.kubernetesSecurity.widgetsToggle.show', { - defaultMessage: 'Show widgets', +export const TREE_VIEW_LOGICAL_VIEW = i18n.translate( + 'xpack.kubernetesSecurity.treeView.logicalView', + { + defaultMessage: 'Logical view', + } +); + +export const TREE_VIEW_INFRASTRUCTURE_VIEW = i18n.translate( + 'xpack.kubernetesSecurity.treeView.infrastructureView', + { + defaultMessage: 'Infrastructure view', + } +); + +export const TREE_VIEW_SWITCHER_LEGEND = i18n.translate( + 'xpack.kubernetesSecurity.treeView.switherLegend', + { + defaultMessage: 'You can switch between the Logical and Infrastructure view', + } +); + +export const TREE_NAVIGATION_LOADING = i18n.translate( + 'xpack.kubernetesSecurity.treeNavigation.loading', + { + defaultMessage: 'Loading', + } +); +export const TREE_NAVIGATION_SHOW_MORE = (name: string) => + i18n.translate('xpack.kubernetesSecurity.treeNavigation.loadMore', { + values: { name }, + defaultMessage: 'Show more {name}', + }); + +export const CHART_TOGGLE_SHOW = i18n.translate('xpack.kubernetesSecurity.chartsToggle.show', { + defaultMessage: 'Show charts', }); -export const WIDGET_TOGGLE_HIDE = i18n.translate('xpack.kubernetesSecurity.widgetsToggle.hide', { - defaultMessage: 'Hide widgets', +export const CHART_TOGGLE_HIDE = i18n.translate('xpack.kubernetesSecurity.chartsToggle.hide', { + defaultMessage: 'Hide charts', }); export const COUNT_WIDGET_CLUSTERS = i18n.translate( @@ -58,3 +91,24 @@ export const COUNT_WIDGET_CONTAINER_IMAGES = i18n.translate( defaultMessage: 'Container Images', } ); + +export const CONTAINER_NAME_SESSION = i18n.translate( + 'xpack.kubernetesSecurity.containerNameWidget.containerImage', + { + defaultMessage: 'Container Images Session', + } +); + +export const CONTAINER_NAME_SESSION_COUNT_COLUMN = i18n.translate( + 'xpack.kubernetesSecurity.containerNameWidget.containerImageCountColumn', + { + defaultMessage: 'Count', + } +); + +export const CONTAINER_NAME_SESSION_ARIA_LABEL = i18n.translate( + 'xpack.kubernetesSecurity.containerNameWidget.containerImageAriaLabel', + { + defaultMessage: 'Container Name Session Widget', + } +); diff --git a/x-pack/plugins/kubernetes_security/common/types/aggregate/index.ts b/x-pack/plugins/kubernetes_security/common/types/aggregate/index.ts index 70747aa8e878d..57a1df44292e9 100644 --- a/x-pack/plugins/kubernetes_security/common/types/aggregate/index.ts +++ b/x-pack/plugins/kubernetes_security/common/types/aggregate/index.ts @@ -5,11 +5,23 @@ * 2.0. */ -export interface AggregateResult { +interface Aggregate { key: string | number; - key_as_string?: string; doc_count: number; +} + +interface Buckets extends Aggregate { + key_as_string?: string; count_by_aggs: { value: number; }; } +export interface AggregateResult { + buckets: Buckets[]; + hasNextPage: boolean; +} + +export interface AggregateBucketPaginationResult { + buckets: Aggregate[]; + hasNextPage: boolean; +} diff --git a/x-pack/plugins/kubernetes_security/public/components/charts_toggle/index.test.tsx b/x-pack/plugins/kubernetes_security/public/components/charts_toggle/index.test.tsx new file mode 100644 index 0000000000000..e0d8249326d55 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/charts_toggle/index.test.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; +import { CHART_TOGGLE_SHOW, CHART_TOGGLE_HIDE } from '../../../common/translations'; +import { ChartsToggle, TOGGLE_TEST_ID } from '.'; + +describe('ChartsToggle component', () => { + let render: () => ReturnType; + let renderResult: ReturnType; + let mockedContext: AppContextTestRender; + const handleToggleHideCharts = jest.fn(); + + beforeEach(() => { + mockedContext = createAppRootMockRenderer(); + }); + + describe('When ChartsToggle is mounted', () => { + it('show "hide charts" text when shouldHideCharts is false', async () => { + renderResult = mockedContext.render( + + ); + + expect(renderResult.getByText(CHART_TOGGLE_HIDE)).toBeVisible(); + }); + it('show "show charts" text when shouldHideCharts is true', async () => { + renderResult = mockedContext.render( + + ); + + expect(renderResult.getByText(CHART_TOGGLE_SHOW)).toBeVisible(); + }); + it('shouldHideCharts defaults to false when not provided', async () => { + renderResult = mockedContext.render( + + ); + + expect(renderResult.getByText(CHART_TOGGLE_HIDE)).toBeVisible(); + }); + it('clicking the toggle fires the callback', async () => { + renderResult = mockedContext.render( + + ); + + renderResult.queryByTestId(TOGGLE_TEST_ID)?.click(); + expect(handleToggleHideCharts).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/x-pack/plugins/kubernetes_security/public/components/charts_toggle/index.tsx b/x-pack/plugins/kubernetes_security/public/components/charts_toggle/index.tsx new file mode 100644 index 0000000000000..d38d1fed3c7aa --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/charts_toggle/index.tsx @@ -0,0 +1,29 @@ +/* + * Copyright 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 { EuiButtonEmpty } from '@elastic/eui'; +import { CHART_TOGGLE_SHOW, CHART_TOGGLE_HIDE } from '../../../common/translations'; + +export const TOGGLE_TEST_ID = 'kubernetesSecurity:chartToggle'; + +interface ChartsToggleDeps { + handleToggleHideCharts: () => void; + shouldHideCharts?: boolean; +} + +export const ChartsToggle = ({ + handleToggleHideCharts, + shouldHideCharts = false, +}: ChartsToggleDeps) => ( + + {shouldHideCharts ? CHART_TOGGLE_SHOW : CHART_TOGGLE_HIDE} + +); diff --git a/x-pack/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.test.tsx b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.test.tsx new file mode 100644 index 0000000000000..8691288bd7c7a --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.test.tsx @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; +import { ContainerNameRow } from './container_name_row'; +import { fireEvent } from '@testing-library/react'; + +const TEST_NAME = 'TEST ROW'; +const TEST_BUTTON_FILTER =
Filter In
; +const TEST_BUTTON_FILTER_OUT =
Filter Out
; + +describe('ContainerNameRow component with valid row', () => { + let renderResult: ReturnType; + const mockedContext = createAppRootMockRenderer(); + const render: () => ReturnType = () => + (renderResult = mockedContext.render( + + )); + + it('should show the row element as well as the pop up filter button when mouse hovers above it', async () => { + render(); + expect(renderResult.getByText(TEST_NAME)).toBeVisible(); + fireEvent.mouseOver(renderResult.queryByText(TEST_NAME)!); + expect(renderResult.getByText('Filter In')).toBeVisible(); + expect(renderResult.getByText('Filter Out')).toBeVisible(); + }); + + it('should show the row element but not the pop up filter button outside mouse hover', async () => { + render(); + expect(renderResult.getByText(TEST_NAME)).toBeVisible(); + expect(renderResult.queryByText('Filter In')).toBeFalsy(); + expect(renderResult.queryByText('Filter Out')).toBeFalsy(); + }); +}); diff --git a/x-pack/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.tsx b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.tsx new file mode 100644 index 0000000000000..50bb4504f5d6d --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { ReactNode, useState } from 'react'; +import { EuiFlexItem, EuiText } from '@elastic/eui'; +import { useStyles } from './styles'; + +export interface ContainerNameRowDeps { + name: string; + filterButtonIn?: ReactNode; + filterButtonOut?: ReactNode; +} + +export const ROW_TEST_ID = 'kubernetesSecurity:containerNameSessionRow'; + +export const ContainerNameRow = ({ + name, + filterButtonIn, + filterButtonOut, +}: ContainerNameRowDeps) => { + const [isHover, setIsHover] = useState(false); + + const styles = useStyles(); + + return ( + setIsHover(true)} + onMouseLeave={() => setIsHover(false)} + data-test-subj={ROW_TEST_ID} + > + + {name} + {isHover && ( +
+ {filterButtonIn} + {filterButtonOut} +
+ )} +
+
+ ); +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/container_name_widget/hooks.ts b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/hooks.ts new file mode 100644 index 0000000000000..66dcbc5b50265 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/hooks.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useInfiniteQuery } from 'react-query'; +import { CoreStart } from '@kbn/core/public'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { QUERY_KEY_CONTAINER_NAME_WIDGET, AGGREGATE_ROUTE } from '../../../common/constants'; +import { AggregateResult } from '../../../common/types/aggregate'; + +export const useFetchContainerNameData = ( + filterQuery: string, + widgetKey: string, + groupBy: string, + countBy?: string, + index?: string, + sortByCount?: string, + pageNumber?: number +) => { + const { http } = useKibana().services; + const cachingKeys = [ + QUERY_KEY_CONTAINER_NAME_WIDGET, + widgetKey, + filterQuery, + groupBy, + countBy, + sortByCount, + pageNumber, + ]; + const query = useInfiniteQuery( + cachingKeys, + async ({ pageParam = 0 }) => { + const res = await http.get(AGGREGATE_ROUTE, { + query: { + query: filterQuery, + groupBy, + countBy, + page: pageParam, + index, + sortByCount, + }, + }); + return res; + }, + { + refetchOnWindowFocus: false, + refetchOnMount: false, + refetchOnReconnect: false, + getNextPageParam: (lastPage, pages) => (lastPage.hasNextPage ? pages.length : undefined), + } + ); + return query; +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.test.tsx b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.test.tsx new file mode 100644 index 0000000000000..bdafb47a8b246 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.test.tsx @@ -0,0 +1,135 @@ +/* + * Copyright 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 { ENTRY_LEADER_ENTITY_ID, CONTAINER_IMAGE_NAME } from '../../../common/constants'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; +import { GlobalFilter } from '../../types'; +import { + ContainerNameWidget, + LOADING_TEST_ID, + NAME_COLUMN_TEST_ID, + COUNT_COLUMN_TEST_ID, + CONTAINER_NAME_TABLE_TEST_ID, +} from '.'; +import { useFetchContainerNameData } from './hooks'; +import { ROW_TEST_ID } from './container_name_row'; + +const TABLE_SORT_BUTTON_ID = 'tableHeaderSortButton'; + +const TITLE = 'Container Images Session'; +const GLOBAL_FILTER: GlobalFilter = { + endDate: '2022-06-15T14:15:25.777Z', + filterQuery: '{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}', + startDate: '2022-05-15T14:15:25.777Z', +}; +const MOCK_DATA = { + pages: [ + { + buckets: [ + { key: 'Container A', doc_count: 295, count_by_aggs: { value: 1 } }, + { key: 'Container B', doc_count: 295, count_by_aggs: { value: 3 } }, + { key: 'Container C', doc_count: 295, count_by_aggs: { value: 2 } }, + { key: 'Container D', doc_count: 295, count_by_aggs: { value: 4 } }, + { key: 'Container E', doc_count: 295, count_by_aggs: { value: 1 } }, + { key: 'Container F', doc_count: 295, count_by_aggs: { value: 1 } }, + { key: 'Container G', doc_count: 295, count_by_aggs: { value: 0 } }, + { key: 'Container H', doc_count: 295, count_by_aggs: { value: 1 } }, + { key: 'Container J', doc_count: 295, count_by_aggs: { value: 1 } }, + { key: 'Container K', doc_count: 295, count_by_aggs: { value: 1 } }, + { key: 'Container L', doc_count: 295, count_by_aggs: { value: 5 } }, + ], + hasNextPage: true, + }, + { + buckets: [ + { key: 'Container A2', doc_count: 295, count_by_aggs: { value: 2 } }, + { key: 'Container B2', doc_count: 295, count_by_aggs: { value: 1 } }, + { key: 'Container C2', doc_count: 295, count_by_aggs: { value: 6 } }, + { key: 'Container D2', doc_count: 295, count_by_aggs: { value: 1 } }, + { key: 'Container E2', doc_count: 295, count_by_aggs: { value: 3 } }, + { key: 'Container F2', doc_count: 295, count_by_aggs: { value: 1 } }, + ], + hasNextPage: false, + }, + ], + pageParams: [undefined], +}; + +jest.mock('../../hooks/use_filter', () => ({ + useSetFilter: () => ({ + getFilterForValueButton: jest.fn(), + getFilterOutValueButton: jest.fn(), + filterManager: {}, + }), +})); + +jest.mock('./hooks'); +const mockUseFetchData = useFetchContainerNameData as jest.Mock; + +describe('ContainerNameWidget component', () => { + let renderResult: ReturnType; + const mockedContext = createAppRootMockRenderer(); + const render: () => ReturnType = () => + (renderResult = mockedContext.render( + + )); + + describe('When ContainerNameWidget is mounted', () => { + describe('with data', () => { + beforeEach(() => { + mockUseFetchData.mockImplementation(() => ({ + data: MOCK_DATA, + isFetchingNextPage: true, + })); + }); + + it('should show the table, table title, table columns, sort button', async () => { + render(); + expect(renderResult.queryByTestId(CONTAINER_NAME_TABLE_TEST_ID)).toBeVisible(); + expect(renderResult.queryAllByTestId(TABLE_SORT_BUTTON_ID)).toHaveLength(1); + expect(renderResult.queryAllByTestId(NAME_COLUMN_TEST_ID)).toHaveLength(17); + expect(renderResult.queryAllByTestId(COUNT_COLUMN_TEST_ID)).toHaveLength(17); + }); + + it('should show data value names and value', async () => { + render(); + expect(renderResult.queryAllByTestId(ROW_TEST_ID)).toHaveLength(17); + }); + }); + + describe('without data ', () => { + it('should show no items found text', async () => { + mockUseFetchData.mockImplementation(() => ({ + data: undefined, + isFetchingNextPage: false, + })); + render(); + expect(renderResult.getByText(TITLE)).toBeVisible(); + expect(renderResult.getByText('No items found')).toBeVisible(); + expect(renderResult.getByTestId(CONTAINER_NAME_TABLE_TEST_ID)).toBeVisible(); + }); + }); + + describe('when loading data', () => { + it('should show progress bar', async () => { + mockUseFetchData.mockImplementation(() => ({ + data: MOCK_DATA, + isFetchingNextPage: false, + isLoading: true, + })); + render(); + expect(renderResult.getByTestId(LOADING_TEST_ID)).toBeVisible(); + }); + }); + }); +}); diff --git a/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.tsx b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.tsx new file mode 100644 index 0000000000000..15f3727efa660 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/index.tsx @@ -0,0 +1,226 @@ +/* + * Copyright 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, { ReactNode, useMemo, useState, useRef, useCallback } from 'react'; +import { EuiBasicTable, EuiTableSortingType, EuiProgress, EuiBasicTableColumn } from '@elastic/eui'; +import { useStyles } from './styles'; +import { ContainerNameRow } from './container_name_row'; +import type { IndexPattern, GlobalFilter } from '../../types'; +import { useSetFilter, useScroll } from '../../hooks'; +import { addTimerangeToQuery } from '../../utils/add_timerange_to_query'; +import { useFetchContainerNameData } from './hooks'; +import { CONTAINER_IMAGE_NAME } from '../../../common/constants'; +import { + CONTAINER_NAME_SESSION, + CONTAINER_NAME_SESSION_COUNT_COLUMN, + CONTAINER_NAME_SESSION_ARIA_LABEL, +} from '../../../common/translations'; + +export const LOADING_TEST_ID = 'kubernetesSecurity:containerNameWidgetLoading'; +export const NAME_COLUMN_TEST_ID = 'kubernetesSecurity:containerImageNameSessionNameColumn'; +export const COUNT_COLUMN_TEST_ID = 'kubernetesSecurity:containerImageNameSessionCountColumn'; +export const CONTAINER_NAME_TABLE_TEST_ID = 'kubernetesSecurity:containerNameSessionTable'; + +export interface ContainerNameWidgetDataValueMap { + key: string; + doc_count: number; + count_by_aggs: { + value: number; + }; +} + +export interface ContainerNameArrayDataValue { + name: string; + count: number; +} + +export interface ContainerNameWidgetDeps { + widgetKey: string; + indexPattern?: IndexPattern; + globalFilter: GlobalFilter; + groupedBy: string; + countBy?: string; +} + +interface FilterButtons { + filterForButtons: ReactNode[]; + filterOutButtons: ReactNode[]; +} + +export const ContainerNameWidget = ({ + widgetKey, + indexPattern, + globalFilter, + groupedBy, + countBy, +}: ContainerNameWidgetDeps) => { + const [sortField, setSortField] = useState('count'); + const [sortDirection, setSortDirection] = useState('desc'); + const styles = useStyles(); + + const filterQueryWithTimeRange = useMemo(() => { + return addTimerangeToQuery( + globalFilter.filterQuery, + globalFilter.startDate, + globalFilter.endDate + ); + }, [globalFilter.filterQuery, globalFilter.startDate, globalFilter.endDate]); + + const { data, fetchNextPage, isFetchingNextPage, isLoading } = useFetchContainerNameData( + filterQueryWithTimeRange, + widgetKey, + groupedBy, + countBy, + indexPattern?.title, + sortDirection + ); + + const onTableChange = useCallback(({ sort = {} }) => { + // @ts-ignore + const { field: sortingField, direction: sortingDirection } = sort; + + setSortField(sortingField); + setSortDirection(sortingDirection); + }, []); + + const sorting: EuiTableSortingType = { + sort: { + field: sortField as keyof ContainerNameArrayDataValue, + direction: sortDirection as 'desc' | 'asc', + }, + enableAllColumns: true, + }; + + const { getFilterForValueButton, getFilterOutValueButton, filterManager } = useSetFilter(); + const filterButtons = useMemo((): FilterButtons => { + const result: FilterButtons = { + filterForButtons: + data?.pages + ?.map((aggsData) => { + return aggsData?.buckets.map((aggData) => { + return getFilterForValueButton({ + field: CONTAINER_IMAGE_NAME, + filterManager, + size: 'xs', + onClick: () => {}, + onFilterAdded: () => {}, + ownFocus: false, + showTooltip: true, + value: aggData.key as string, + }); + }); + }) + .flat() || [], + + filterOutButtons: + data?.pages + ?.map((aggsData) => { + return aggsData?.buckets.map((aggData) => { + return getFilterOutValueButton({ + field: CONTAINER_IMAGE_NAME, + filterManager, + size: 'xs', + onClick: () => {}, + onFilterAdded: () => {}, + ownFocus: false, + showTooltip: true, + value: aggData.key as string, + }); + }); + }) + .flat() || [], + }; + return result; + }, [data, getFilterForValueButton, getFilterOutValueButton, filterManager]); + + const containerNameArray = useMemo((): ContainerNameArrayDataValue[] => { + return data + ? data?.pages + ?.map((aggsData) => { + return aggsData?.buckets.map((aggData) => { + return { + name: aggData.key as string, + count: aggData.count_by_aggs.value, + }; + }); + }) + .flat() + : []; + }, [data]); + + const columns = useMemo((): Array> => { + return [ + { + field: 'name', + name: CONTAINER_NAME_SESSION, + 'data-test-subj': NAME_COLUMN_TEST_ID, + render: (name: string) => { + const indexHelper = containerNameArray.findIndex((obj) => { + return obj.name === name; + }); + + return ( + + ); + }, + align: 'left', + width: '74%', + sortable: false, + }, + { + field: 'count', + name: CONTAINER_NAME_SESSION_COUNT_COLUMN, + width: '26%', + 'data-test-subj': COUNT_COLUMN_TEST_ID, + render: (count: number) => { + return {count}; + }, + sortable: true, + align: 'right', + }, + ]; + }, [filterButtons.filterForButtons, filterButtons.filterOutButtons, containerNameArray, styles]); + + const scrollerRef = useRef(null); + useScroll({ + div: scrollerRef.current, + handler: (pos: number, endReached: boolean) => { + if (!isFetchingNextPage && endReached) { + fetchNextPage(); + } + }, + }); + + return ( +
+ {isLoading && ( + + )} + +
+ ); +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/container_name_widget/styles.ts b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/styles.ts new file mode 100644 index 0000000000000..7e676b3e03445 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/container_name_widget/styles.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import { CSSObject } from '@emotion/react'; +import { transparentize } from '@elastic/eui'; +import { useEuiTheme } from '../../hooks'; + +export const useStyles = () => { + const { euiTheme } = useEuiTheme(); + + const cached = useMemo(() => { + const { size, font, colors } = euiTheme; + + const container: CSSObject = { + padding: size.base, + border: euiTheme.border.thin, + borderRadius: euiTheme.border.radius.medium, + overflow: 'auto', + height: '100%', + minHeight: '250px', + position: 'relative', + marginBottom: size.l, + }; + + const dataInfo: CSSObject = { + marginBottom: size.xs, + display: 'flex', + alignItems: 'center', + height: size.l, + position: 'relative', + }; + + const filters: CSSObject = { + marginLeft: size.s, + position: 'absolute', + left: '50%', + backgroundColor: colors.emptyShade, + borderRadius: euiTheme.border.radius.small, + border: euiTheme.border.thin, + bottom: '-25px', + boxShadow: `0 ${size.xs} ${size.xs} ${transparentize(euiTheme.colors.shadow, 0.04)}`, + }; + + const countValue: CSSObject = { + fontWeight: font.weight.semiBold, + }; + + return { + container, + dataInfo, + filters, + countValue, + }; + }, [euiTheme]); + + return cached; +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/count_widget/index.test.tsx b/x-pack/plugins/kubernetes_security/public/components/count_widget/index.test.tsx index 72d087f47d364..a0fbe2c90c690 100644 --- a/x-pack/plugins/kubernetes_security/public/components/count_widget/index.test.tsx +++ b/x-pack/plugins/kubernetes_security/public/components/count_widget/index.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; import { GlobalFilter } from '../../types'; -import { CountWidget, LOADING_TEST_ID, TOOLTIP_TEST_ID } from '.'; +import { CountWidget, LOADING_TEST_ID, TOOLTIP_TEST_ID, VALUE_TEST_ID } from '.'; import { useFetchCountWidgetData } from './hooks'; import { fireEvent, waitFor } from '@testing-library/dom'; @@ -137,9 +137,9 @@ describe('CountWidget component', () => { isLoading: false, })); render(); - fireEvent.mouseOver(renderResult.getByText('Info')); + fireEvent.mouseOver(renderResult.getByTestId(VALUE_TEST_ID)); await waitFor(() => renderResult.getByTestId(TOOLTIP_TEST_ID)); - expect(renderResult.queryByText(MOCK_DATA_THOUSAND.pages[0])).toBeTruthy(); + expect(renderResult.queryByText('5,236')).toBeTruthy(); }); }); }); diff --git a/x-pack/plugins/kubernetes_security/public/components/count_widget/index.tsx b/x-pack/plugins/kubernetes_security/public/components/count_widget/index.tsx index 5e5f5eacc374f..534187057b5e9 100644 --- a/x-pack/plugins/kubernetes_security/public/components/count_widget/index.tsx +++ b/x-pack/plugins/kubernetes_security/public/components/count_widget/index.tsx @@ -6,9 +6,10 @@ */ import React, { useMemo } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiText, EuiLoadingSpinner, EuiIconTip } from '@elastic/eui'; +import { EuiText, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; import { useStyles } from './styles'; import type { IndexPattern, GlobalFilter } from '../../types'; +import { addCommasToNumber } from '../../utils/add_commas_to_number'; import { addTimerangeToQuery } from '../../utils/add_timerange_to_query'; import { useFetchCountWidgetData } from './hooks'; import { addResourceTypeToFilterQuery, numberFormatter } from './helpers'; @@ -16,6 +17,7 @@ import { COUNT_WIDGET_KEY_PODS } from '../../../common/constants'; export const LOADING_TEST_ID = 'kubernetesSecurity:countWidgetLoading'; export const TOOLTIP_TEST_ID = 'kubernetesSecurity:countWidgetTooltip'; +export const VALUE_TEST_ID = 'kubernetesSecurity:countWidgetValue'; export interface CountWidgetDeps { title: string; @@ -60,26 +62,21 @@ export const CountWidget = ({ return (
-
- {title} - -
- - - - {isLoading ? ( - - ) : ( - formattedNumber - )} - - - +
{title}
+ + + {isLoading ? ( + + ) : ( + formattedNumber + )} + +
); }; diff --git a/x-pack/plugins/kubernetes_security/public/components/count_widget/styles.ts b/x-pack/plugins/kubernetes_security/public/components/count_widget/styles.ts index abd89925b5cf3..adea8ee704c97 100644 --- a/x-pack/plugins/kubernetes_security/public/components/count_widget/styles.ts +++ b/x-pack/plugins/kubernetes_security/public/components/count_widget/styles.ts @@ -21,6 +21,7 @@ export const useStyles = () => { borderRadius: border.radius.medium, overflow: 'auto', position: 'relative', + height: '100%', }; const title: CSSObject = { @@ -31,8 +32,6 @@ export const useStyles = () => { const dataInfo: CSSObject = { marginBottom: size.xs, - display: 'flex', - alignItems: 'center', height: '18px', fontSize: size.l, fontWeight: font.weight.bold, diff --git a/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.test.tsx b/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.test.tsx index 5399975091420..ea9b8b11da891 100644 --- a/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.test.tsx +++ b/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.test.tsx @@ -25,6 +25,10 @@ jest.mock('../count_widget', () => ({ CountWidget: () =>
{'Mock count widget'}
, })); +jest.mock('../container_name_widget', () => ({ + ContainerNameWidget: () =>
{'Mock Container Name widget'}
, +})); + const renderWithRouter = ( initialEntries: MemoryRouterProps['initialEntries'] = ['/kubernetes'] ) => { diff --git a/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx b/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx index 182873f954d8d..26c0b041ab18f 100644 --- a/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx +++ b/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx @@ -36,7 +36,7 @@ import { AggregateResult } from '../../../common/types/aggregate'; import { useLastUpdated } from '../../hooks'; import { useStyles } from './styles'; import { TreeViewContainer } from '../tree_view_container'; -import { WidgetsToggle } from '../widgets_toggle'; +import { ChartsToggle } from '../charts_toggle'; import { COUNT_WIDGET_CLUSTERS, COUNT_WIDGET_NAMESPACE, @@ -44,6 +44,7 @@ import { COUNT_WIDGET_PODS, COUNT_WIDGET_CONTAINER_IMAGES, } from '../../../common/translations'; +import { ContainerNameWidget } from '../container_name_widget'; const KubernetesSecurityRoutesComponent = ({ filter, @@ -51,7 +52,7 @@ const KubernetesSecurityRoutesComponent = ({ globalFilter, renderSessionsView, }: KubernetesSecurityDeps) => { - const [shouldHideWidgets, setShouldHideWidgets] = useLocalStorage( + const [shouldHideCharts, setShouldHideCharts] = useLocalStorage( LOCAL_STORAGE_HIDE_WIDGETS_KEY, false ); @@ -59,8 +60,8 @@ const KubernetesSecurityRoutesComponent = ({ const lastUpdated = useLastUpdated(globalFilter); const onReduceInteractiveAggs = useCallback( - (result: AggregateResult[]): Record => - result.reduce((groupedByKeyValue, aggregate) => { + (result: AggregateResult): Record => + result.buckets.reduce((groupedByKeyValue, aggregate) => { groupedByKeyValue[aggregate.key_as_string || (aggregate.key.toString() as string)] = aggregate.count_by_aggs.value; return groupedByKeyValue; @@ -69,9 +70,9 @@ const KubernetesSecurityRoutesComponent = ({ ); const onReduceRootAggs = useCallback( - (result: AggregateResult[]): Record => - result.reduce((groupedByKeyValue, aggregate) => { - if (aggregate.key === '0') { + (result: AggregateResult): Record => + result.buckets.reduce((groupedByKeyValue, aggregate) => { + if (aggregate.key.toString() === '0') { groupedByKeyValue[aggregate.key] = aggregate.count_by_aggs.value; } else { groupedByKeyValue.nonRoot = @@ -82,9 +83,9 @@ const KubernetesSecurityRoutesComponent = ({ [] ); - const handleToggleHideWidgets = useCallback(() => { - setShouldHideWidgets(!shouldHideWidgets); - }, [setShouldHideWidgets, shouldHideWidgets]); + const handleToggleHideCharts = useCallback(() => { + setShouldHideCharts(!shouldHideCharts); + }, [setShouldHideCharts, shouldHideCharts]); return ( @@ -98,185 +99,182 @@ const KubernetesSecurityRoutesComponent = ({
{lastUpdated}
-
- {!shouldHideWidgets && ( + {!shouldHideCharts && ( <> - - - + + + - - - - - - - - - - - - - - - - - + - - - - - - - - } + + + + + + + + + + + + + + + + + + + - - } - widgetKey="sessionsPercentage" - indexPattern={indexPattern} - globalFilter={globalFilter} - dataValueMap={{ - true: { - name: i18n.translate( - 'xpack.kubernetesSecurity.sessionChart.interactive', - { - defaultMessage: 'Interactive', - } - ), - fieldName: ENTRY_LEADER_INTERACTIVE, - color: euiThemeVars.euiColorVis0, - }, - false: { - name: i18n.translate( - 'xpack.kubernetesSecurity.sessionChart.nonInteractive', - { - defaultMessage: 'Non-interactive', - } - ), - fieldName: ENTRY_LEADER_INTERACTIVE, - color: euiThemeVars.euiColorVis1, - shouldHideFilter: true, - }, - }} - groupedBy={ENTRY_LEADER_INTERACTIVE} - countBy={ENTRY_LEADER_ENTITY_ID} - onReduce={onReduceInteractiveAggs} - /> - - - - - - - - } + } + /> + + } + widgetKey="sessionsPercentage" + indexPattern={indexPattern} + globalFilter={globalFilter} + dataValueMap={{ + true: { + name: i18n.translate( + 'xpack.kubernetesSecurity.sessionChart.interactive', + { + defaultMessage: 'Interactive', + } + ), + fieldName: ENTRY_LEADER_INTERACTIVE, + color: euiThemeVars.euiColorVis0, + }, + false: { + name: i18n.translate( + 'xpack.kubernetesSecurity.sessionChart.nonInteractive', + { + defaultMessage: 'Non-interactive', + } + ), + fieldName: ENTRY_LEADER_INTERACTIVE, + color: euiThemeVars.euiColorVis1, + shouldHideFilter: true, + }, + }} + groupedBy={ENTRY_LEADER_INTERACTIVE} + countBy={ENTRY_LEADER_ENTITY_ID} + onReduce={onReduceInteractiveAggs} + /> + + + + + + + - - } - widgetKey="rootLoginPercentage" - indexPattern={indexPattern} - globalFilter={globalFilter} - dataValueMap={{ - '0': { - name: i18n.translate('xpack.kubernetesSecurity.entryUserChart.root', { - defaultMessage: 'Root', - }), - fieldName: ENTRY_LEADER_USER_ID, - color: euiThemeVars.euiColorVis2, - }, - nonRoot: { - name: i18n.translate( - 'xpack.kubernetesSecurity.entryUserChart.nonRoot', - { - defaultMessage: 'Non-root', - } - ), - fieldName: ENTRY_LEADER_USER_ID, - color: euiThemeVars.euiColorVis3, - shouldHideFilter: true, - }, - }} - groupedBy={ENTRY_LEADER_USER_ID} - countBy={ENTRY_LEADER_ENTITY_ID} - onReduce={onReduceRootAggs} - /> - - + } + /> + + } + widgetKey="rootLoginPercentage" + indexPattern={indexPattern} + globalFilter={globalFilter} + dataValueMap={{ + '0': { + name: i18n.translate('xpack.kubernetesSecurity.entryUserChart.root', { + defaultMessage: 'Root', + }), + fieldName: ENTRY_LEADER_USER_ID, + color: euiThemeVars.euiColorVis2, + }, + nonRoot: { + name: i18n.translate('xpack.kubernetesSecurity.entryUserChart.nonRoot', { + defaultMessage: 'Non-root', + }), + fieldName: ENTRY_LEADER_USER_ID, + color: euiThemeVars.euiColorVis3, + shouldHideFilter: true, + }, + }} + groupedBy={ENTRY_LEADER_USER_ID} + countBy={ENTRY_LEADER_ENTITY_ID} + onReduce={onReduceRootAggs} + /> - - - -
PlaceHolder for Container Name Widget
-
-
+ +
)} - +
); diff --git a/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/styles.ts b/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/styles.ts index 889f99715393b..aa35cd8a22a4f 100644 --- a/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/styles.ts +++ b/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/styles.ts @@ -48,8 +48,26 @@ export const useStyles = () => { height: '500px', }; - const percentageWidgets: CSSObject = { - marginBottom: size.l, + const widgetsBottomSpacing: CSSObject = { + marginBottom: size.m, + }; + + const noBottomSpacing: CSSObject = { + marginBottom: 0, + }; + + const countWidgetsGroup: CSSObject = { + ...widgetsBottomSpacing, + flexWrap: 'wrap', + }; + + const leftWidgetsGroup: CSSObject = { + ...noBottomSpacing, + minWidth: `calc(70% - ${size.xxxl})`, + }; + + const rightWidgetsGroup: CSSObject = { + minWidth: '30%', }; const percentageChartTitle: CSSObject = { @@ -58,16 +76,10 @@ export const useStyles = () => { fontWeight: font.weight.bold, }; - const countWidgets: CSSObject = { - margin: size.l, - }; - const widgetHolder: CSSObject = { position: 'relative', width: '332px', height: '235px', - padding: size.base, - border: border.thin, borderRadius: border.radius.medium, fontWeight: font.weight.bold, fontSize: size.m, @@ -80,9 +92,12 @@ export const useStyles = () => { updatedAt, widgetBadge, treeViewContainer, - percentageWidgets, + countWidgetsGroup, + leftWidgetsGroup, + rightWidgetsGroup, + widgetsBottomSpacing, percentageChartTitle, - countWidgets, + noBottomSpacing, widgetHolder, }; }, [euiTheme]); diff --git a/x-pack/plugins/kubernetes_security/public/components/percent_widget/hooks.ts b/x-pack/plugins/kubernetes_security/public/components/percent_widget/hooks.ts index decdb0c6e27a9..f13cdfa0ac7a4 100644 --- a/x-pack/plugins/kubernetes_security/public/components/percent_widget/hooks.ts +++ b/x-pack/plugins/kubernetes_security/public/components/percent_widget/hooks.ts @@ -11,7 +11,7 @@ import { QUERY_KEY_PERCENT_WIDGET, AGGREGATE_ROUTE } from '../../../common/const import { AggregateResult } from '../../../common/types/aggregate'; export const useFetchPercentWidgetData = ( - onReduce: (result: AggregateResult[]) => Record, + onReduce: (result: AggregateResult) => Record, filterQuery: string, widgetKey: string, groupBy: string, @@ -20,27 +20,19 @@ export const useFetchPercentWidgetData = ( ) => { const { http } = useKibana().services; const cachingKeys = [QUERY_KEY_PERCENT_WIDGET, widgetKey, filterQuery, groupBy, countBy, index]; - const query = useQuery( - cachingKeys, - async (): Promise> => { - const res = await http.get(AGGREGATE_ROUTE, { - query: { - query: filterQuery, - groupBy, - countBy, - page: 0, - index, - }, - }); + const query = useQuery(cachingKeys, async (): Promise> => { + const res = await http.get(AGGREGATE_ROUTE, { + query: { + query: filterQuery, + groupBy, + countBy, + page: 0, + index, + }, + }); - return onReduce(res); - }, - { - refetchOnWindowFocus: false, - refetchOnMount: false, - refetchOnReconnect: false, - } - ); + return onReduce(res); + }); return query; }; diff --git a/x-pack/plugins/kubernetes_security/public/components/percent_widget/index.tsx b/x-pack/plugins/kubernetes_security/public/components/percent_widget/index.tsx index 0c3cb3da9c5a8..21c068978a345 100644 --- a/x-pack/plugins/kubernetes_security/public/components/percent_widget/index.tsx +++ b/x-pack/plugins/kubernetes_security/public/components/percent_widget/index.tsx @@ -32,7 +32,7 @@ export interface PercentWidgetDeps { globalFilter: GlobalFilter; groupedBy: string; countBy?: string; - onReduce: (result: AggregateResult[]) => Record; + onReduce: (result: AggregateResult) => Record; } interface FilterButtons { diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/__snapshots__/index.test.tsx.snap b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/__snapshots__/index.test.tsx.snap new file mode 100644 index 0000000000000..97a7fdd38f611 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/__snapshots__/index.test.tsx.snap @@ -0,0 +1,435 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Tree view Breadcrumb component When Breadcrumb is mounted renders Breadcrumb correctly 1`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+
+ + + + + + + + + + + +
+
+ , + "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[`Tree view Breadcrumb component When Breadcrumb is mounted renders provided collections only 1`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+
+ + + + + + + + +
+
+ , + "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], +} +`; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.test.tsx b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.test.tsx new file mode 100644 index 0000000000000..1c127294ea7bb --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.test.tsx @@ -0,0 +1,103 @@ +/* + * Copyright 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 { AppContextTestRender, createAppRootMockRenderer } from '../../../test'; +import { KubernetesCollection, TreeNavSelection } from '../../../types'; +import { Breadcrumb } from '.'; + +const MOCK_TREE_SELECTION: TreeNavSelection = { + [KubernetesCollection.cluster]: 'selected cluster', + [KubernetesCollection.namespace]: 'selected namespace', + [KubernetesCollection.node]: 'selected node', + [KubernetesCollection.pod]: 'selected pod', + [KubernetesCollection.containerImage]: 'selected image', +}; + +describe('Tree view Breadcrumb component', () => { + let render: () => ReturnType; + let renderResult: ReturnType; + let mockedContext: AppContextTestRender; + let onSelect: jest.Mock; + + beforeEach(() => { + mockedContext = createAppRootMockRenderer(); + onSelect = jest.fn(); + }); + + describe('When Breadcrumb is mounted', () => { + it('renders Breadcrumb correctly', async () => { + renderResult = mockedContext.render( + + ); + + expect( + renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.cluster]!) + ).toBeVisible(); + expect( + renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.namespace]!) + ).toBeVisible(); + expect(renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.node]!)).toBeFalsy(); + expect( + renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.pod]!) + ).toBeVisible(); + expect( + renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.containerImage]!) + ).toBeVisible(); + expect(renderResult).toMatchSnapshot(); + }); + + it('returns null when no selected collection', async () => { + renderResult = mockedContext.render(); + + expect(renderResult.container).toBeEmptyDOMElement(); + }); + + it('returns null when no cluster in selection', async () => { + renderResult = mockedContext.render( + + ); + + expect(renderResult.container).toBeEmptyDOMElement(); + }); + + it('renders provided collections only', async () => { + renderResult = mockedContext.render( + + ); + + expect( + renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.cluster]!) + ).toBeVisible(); + expect( + renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.namespace]!) + ).toBeFalsy(); + expect( + renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.node]!) + ).toBeVisible(); + expect(renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.pod]!)).toBeFalsy(); + expect( + renderResult.queryByText(MOCK_TREE_SELECTION[KubernetesCollection.containerImage]!) + ).toBeVisible(); + expect(renderResult).toMatchSnapshot(); + }); + }); +}); diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.tsx b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.tsx new file mode 100644 index 0000000000000..ddef4abd86481 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.tsx @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback } from 'react'; +import { EuiButtonEmpty, EuiIcon } from '@elastic/eui'; +import { TreeNavSelection, KubernetesCollection } from '../../../types'; +import { useStyles } from './styles'; + +interface BreadcrumbDeps { + treeNavSelection: TreeNavSelection; + onSelect: (selection: TreeNavSelection) => void; +} + +export const Breadcrumb = ({ treeNavSelection, onSelect }: BreadcrumbDeps) => { + const styles = useStyles(); + const onBreadCrumbClick = useCallback( + (collectionType: string) => { + const selectionCopy = { ...treeNavSelection }; + switch (collectionType) { + case KubernetesCollection.cluster: { + onSelect({ + [KubernetesCollection.cluster]: treeNavSelection[KubernetesCollection.cluster], + }); + break; + } + case KubernetesCollection.namespace: + case KubernetesCollection.node: { + delete selectionCopy[KubernetesCollection.pod]; + delete selectionCopy[KubernetesCollection.containerImage]; + onSelect(selectionCopy); + break; + } + case KubernetesCollection.pod: { + delete selectionCopy[KubernetesCollection.containerImage]; + onSelect(selectionCopy); + break; + } + } + }, + [onSelect, treeNavSelection] + ); + + const renderBreadcrumbLink = useCallback( + ( + collectionType: KubernetesCollection, + icon: JSX.Element, + isBolded: boolean, + hasRightArrow: boolean = true + ) => ( + <> + {hasRightArrow && } + {icon} + onBreadCrumbClick(collectionType)} + > + {treeNavSelection[collectionType]} + + + ), + [ + onBreadCrumbClick, + styles.breadcrumbButton, + styles.breadcrumbButtonBold, + styles.breadcrumbRightIcon, + treeNavSelection, + ] + ); + + if (!treeNavSelection[KubernetesCollection.cluster]) { + return null; + } + + return ( +
+ {renderBreadcrumbLink( + KubernetesCollection.cluster, + , + !( + treeNavSelection[KubernetesCollection.namespace] || + treeNavSelection[KubernetesCollection.node] + ), + false + )} + {treeNavSelection[KubernetesCollection.namespace] && + renderBreadcrumbLink( + KubernetesCollection.namespace, + , + !treeNavSelection[KubernetesCollection.pod] + )} + {treeNavSelection[KubernetesCollection.node] && + renderBreadcrumbLink( + KubernetesCollection.node, + , + !treeNavSelection[KubernetesCollection.pod] + )} + {treeNavSelection[KubernetesCollection.pod] && + renderBreadcrumbLink( + KubernetesCollection.pod, + , + !treeNavSelection[KubernetesCollection.containerImage] + )} + {treeNavSelection[KubernetesCollection.containerImage] && + renderBreadcrumbLink( + KubernetesCollection.containerImage, + , + true + )} +
+ ); +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/styles.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/styles.ts new file mode 100644 index 0000000000000..e2a5f297b04f0 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/styles.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import { CSSObject } from '@emotion/react'; +import { useEuiTheme } from '../../../hooks'; + +export const useStyles = () => { + const { euiTheme } = useEuiTheme(); + + const cached = useMemo(() => { + const { colors, size, font, border } = euiTheme; + + const breadcrumb: CSSObject = { + borderBottom: border.thin, + borderColor: colors.lightShade, + paddingBottom: size.s, + marginBottom: size.m, + }; + + const breadcrumbButton: CSSObject = { + height: 'fit-content', + maxWidth: '248px', + fontWeight: font.weight.regular, + '.euiButtonEmpty__content': { + paddingLeft: size.xs, + paddingRight: size.xs, + }, + }; + + const breadcrumbButtonBold: CSSObject = { + ...breadcrumbButton, + fontWeight: font.weight.semiBold, + }; + + const breadcrumbRightIcon: CSSObject = { + marginRight: size.xs, + }; + + return { + breadcrumb, + breadcrumbButton, + breadcrumbButtonBold, + breadcrumbRightIcon, + }; + }, [euiTheme]); + + return cached; +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.test.tsx b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.test.tsx new file mode 100644 index 0000000000000..b9851f65df2cb --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.test.tsx @@ -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 React, { FC } from 'react'; +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { focusNextElement } from './helpers'; + +// dummy component for testing +const TestButtonList: FC = (props: any) => ( + <> + {[...Array(100)].map((_, idx) => ( + + ))} + +); + +describe('DynamicTreeView component', () => { + it('Should focus the next element', async () => { + const onKeyDown = (e: any) => { + focusNextElement(e, 'button', 'next'); + }; + const wrapper = render(); + wrapper.getByText('Button 40').focus(); + + userEvent.keyboard('{ArrowRight}'); + expect(wrapper.getByText('Button 41')).toHaveFocus(); + userEvent.keyboard('{ArrowRight}'); + expect(wrapper.getByText('Button 42')).toHaveFocus(); + }); + it('Should focus the previous element', async () => { + const onKeyDown = (e: any) => { + focusNextElement(e, 'button', 'prev'); + }; + const wrapper = render(); + wrapper.getByText('Button 40').focus(); + + userEvent.keyboard('{ArrowLeft}'); + expect(wrapper.getByText('Button 39')).toHaveFocus(); + userEvent.keyboard('{ArrowLeft}'); + expect(wrapper.getByText('Button 38')).toHaveFocus(); + }); +}); diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.ts new file mode 100644 index 0000000000000..774ea3eb10ee5 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.ts @@ -0,0 +1,29 @@ +/* + * Copyright 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 { KeyboardEvent, MouseEvent } from 'react'; + +export const disableEventDefaults = (event: KeyboardEvent | MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); +}; + +export const focusNextElement = ( + event: KeyboardEvent, + selector: string, + direction: 'prev' | 'next' +) => { + const list = Array.from(document.querySelectorAll(selector)); + const currentIndex = list.indexOf(event.currentTarget); + if (currentIndex > -1) { + const nextButton = list[currentIndex + (direction === 'next' ? +1 : -1)] as HTMLElement; + if (nextButton) { + disableEventDefaults(event); + nextButton.focus(); + } + } +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/hooks.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/hooks.ts new file mode 100644 index 0000000000000..7607b7253ada5 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/hooks.ts @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { useInfiniteQuery } from 'react-query'; +import { CoreStart } from '@kbn/core/public'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { QueryDslQueryContainerBool } from '../../../types'; +import { QUERY_KEY_PROCESS_EVENTS, AGGREGATE_ROUTE } from '../../../../common/constants'; +import { AggregateBucketPaginationResult } from '../../../../common/types/aggregate'; + +export const useFetchDynamicTreeView = ( + query: QueryDslQueryContainerBool, + groupBy: string, + index?: string, + enabled?: boolean +) => { + const { http } = useKibana().services; + const cachingKeys = [QUERY_KEY_PROCESS_EVENTS, query, groupBy, index]; + + return useInfiniteQuery( + cachingKeys, + async ({ pageParam = 0 }) => + await http.get(AGGREGATE_ROUTE, { + query: { + query: JSON.stringify(query), + groupBy, + page: pageParam, + perPage: 50, + index, + }, + }), + { + enabled, + getNextPageParam: (lastPage, pages) => (lastPage.hasNextPage ? pages.length : undefined), + } + ); +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.test.tsx b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.test.tsx new file mode 100644 index 0000000000000..c61de91b6884d --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.test.tsx @@ -0,0 +1,178 @@ +/* + * Copyright 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 { waitFor } from '@testing-library/react'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../../test'; +import { DynamicTreeView } from '.'; +import { clusterResponseMock, nodeResponseMock } from './mocks'; + +describe('DynamicTreeView component', () => { + let render: (props?: any) => ReturnType; + let renderResult: ReturnType; + let mockedContext: AppContextTestRender; + let mockedApi: AppContextTestRender['coreStart']['http']['get']; + + const waitForApiCall = () => waitFor(() => expect(mockedApi).toHaveBeenCalled()); + + beforeEach(() => { + mockedContext = createAppRootMockRenderer(); + mockedApi = mockedContext.coreStart.http.get; + mockedApi.mockResolvedValue(clusterResponseMock); + render = (props) => + (renderResult = mockedContext.render( + {}} + {...props} + /> + )); + }); + + describe('When DynamicTreeView is mounted', () => { + it('should show loading state while retrieving empty data and hide it when settled', async () => { + render(); + expect(renderResult.queryByText(/loading/i)).toBeInTheDocument(); + await waitForApiCall(); + expect(renderResult.queryByText(/loading/i)).not.toBeInTheDocument(); + }); + }); + + describe('DynamicTreeView parent level', () => { + const key = 'cluster-test'; + const tree = [ + { + key, + name: 'cluster', + namePlural: 'clusters', + type: 'cluster', + iconProps: { + type: 'cluster', + }, + }, + ]; + + it('should make a api call with group based on tree parameters', async () => { + render({ + tree, + }); + await waitForApiCall(); + + expect(mockedApi).toHaveBeenCalledWith('/internal/kubernetes_security/aggregate', { + query: { + groupBy: key, + index: '*-logs', + page: 0, + perPage: 50, + query: '{"bool":{"filter":[],"must":[],"must_not":[],"should":[]}}', + }, + }); + }); + + it('should render the parent level based on api response', async () => { + render({ + tree, + }); + await waitForApiCall(); + + ['awp-demo-gke-main', 'awp-demo-gke-test'].forEach((cluster) => { + expect(renderResult.queryByText(cluster)).toBeInTheDocument(); + }); + }); + + it('should trigger a callback when tree node is clicked', async () => { + const callback = jest.fn(); + render({ tree, onSelect: callback }); + await waitForApiCall(); + + renderResult.getByRole('button', { name: 'awp-demo-gke-main' }).click(); + + expect(callback).toHaveBeenCalled(); + }); + }); + + describe('DynamicTreeView children', () => { + const tree = [ + { + key: 'cluster', + name: 'cluster', + namePlural: 'clusters', + type: 'cluster', + iconProps: { + type: 'cluster', + }, + }, + { + key: 'node', + name: 'node', + namePlural: 'nodes', + type: 'node', + iconProps: { + type: 'node', + }, + }, + ]; + + const parent = 'awp-demo-gke-main'; + + it('should make a children api call with filter when parent is expanded', async () => { + render({ tree }); + await waitForApiCall(); + renderResult.getByRole('button', { name: parent }).click(); + + mockedApi.mockResolvedValueOnce(nodeResponseMock); + + await waitForApiCall(); + expect(mockedApi).toHaveBeenCalledWith('/internal/kubernetes_security/aggregate', { + query: { + groupBy: 'node', + index: '*-logs', + page: 0, + perPage: 50, + query: `{"bool":{"filter":[{"term":{"cluster":"${parent}"}}],"must":[],"must_not":[],"should":[]}}`, + }, + }); + }); + + it('should render children when parent is expanded based on api request', async () => { + render({ tree }); + await waitForApiCall(); + + renderResult.getByRole('button', { name: parent }).click(); + + mockedApi.mockResolvedValueOnce(nodeResponseMock); + + // check if children has loading state + expect(renderResult.queryByText(/loading/i)).toBeInTheDocument(); + await waitForApiCall(); + + ['default', 'kube-system', 'production', 'qa', 'staging'].forEach((node) => { + expect(renderResult.queryByText(node)).toBeInTheDocument(); + }); + }); + }); +}); diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.tsx b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.tsx new file mode 100644 index 0000000000000..bed7238d59ec4 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.tsx @@ -0,0 +1,331 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useState, useRef, MouseEvent, KeyboardEvent, useMemo } from 'react'; +import { + EuiIcon, + EuiText, + EuiI18n, + EuiScreenReaderOnly, + EuiBadge, + keys, + EuiLoadingSpinner, +} from '@elastic/eui'; +import { + TREE_NAVIGATION_LOADING, + TREE_NAVIGATION_SHOW_MORE, +} from '../../../../common/translations'; +import { useFetchDynamicTreeView } from './hooks'; +import { useStyles } from './styles'; +import { disableEventDefaults, focusNextElement } from './helpers'; +import type { DynamicTreeViewProps, DynamicTreeViewItemProps } from './types'; + +const BUTTON_TEST_ID = 'kubernetesSecurity:dynamicTreeViewButton'; + +const focusNextButton = (event: KeyboardEvent) => { + focusNextElement(event, `[data-test-subj="${BUTTON_TEST_ID}"]`, 'next'); +}; +const focusPreviousButton = (event: KeyboardEvent) => { + focusNextElement(event, `[data-test-subj="${BUTTON_TEST_ID}"]`, 'prev'); +}; + +const DynamicTreeViewExpander = ({ + children, +}: { + children: (childrenProps: { isExpanded: boolean; onToggleExpand: () => void }) => JSX.Element; +}) => { + const [isExpanded, setIsExpanded] = useState(false); + + const onToggleExpand = () => { + setIsExpanded((e) => !e); + }; + + return children({ + isExpanded, + onToggleExpand, + }); +}; + +export const DynamicTreeView = ({ + tree, + depth = 0, + selectionDepth = {}, + query, + indexPattern = '', + onSelect, + hasSelection, + selected = '', + expanded = true, + ...props +}: DynamicTreeViewProps) => { + const styles = useStyles(depth); + + const { data, fetchNextPage, isFetchingNextPage, hasNextPage, isLoading } = + useFetchDynamicTreeView(query, tree[depth].key, indexPattern, expanded); + + const ariaLabel = props['aria-label']; + + const onLoadMoreKeydown = (event: React.KeyboardEvent) => { + switch (event.key) { + case keys.ARROW_DOWN: { + focusNextButton(event); + break; + } + case keys.ARROW_UP: { + focusPreviousButton(event); + break; + } + case keys.ARROW_RIGHT: { + disableEventDefaults(event); + fetchNextPage(); + } + } + }; + + useEffect(() => { + if (expanded) { + fetchNextPage(); + } + }, [fetchNextPage, expanded]); + + useEffect(() => { + if (!hasSelection && !depth && data && data.pages?.[0].buckets?.[0]?.key) { + onSelect({}, data.pages[0].buckets[0].key, tree[depth].type); + } + }, [data, depth, hasSelection, onSelect, tree]); + + const onClickNextPageHandler = () => { + fetchNextPage(); + }; + + const itemList = useMemo(() => { + return ( + data?.pages + ?.map((aggsData) => { + return aggsData?.buckets; + }) + .flat() || [] + ); + }, [data?.pages]); + + return ( + + {isLoading && ( +
+ + {TREE_NAVIGATION_LOADING} +
+ )} + {depth === 0 && ( + + {(listNavigationInstructions: string) => ( + +

{listNavigationInstructions}

+
+ )} +
+ )} +
    + {itemList.map((aggData) => { + const queryFilter = { + ...query, + bool: { + ...query.bool, + filter: [...query.bool.filter, { term: { [tree[depth].key]: aggData.key } }], + }, + }; + + return ( + + {({ isExpanded, onToggleExpand }) => ( + + )} + + ); + })} + {hasNextPage && ( +
  • + onLoadMoreKeydown(event)} + onClick={onClickNextPageHandler} + > + + {isFetchingNextPage + ? TREE_NAVIGATION_LOADING + : TREE_NAVIGATION_SHOW_MORE(tree[depth].namePlural)} + + {isFetchingNextPage ? ( + + ) : ( + + )} + +
  • + )} +
+
+ ); +}; + +const DynamicTreeViewItem = ({ + depth, + tree, + onToggleExpand, + onSelect, + aggData, + selectionDepth, + isExpanded, + selected, + expanded, + query, + indexPattern, + ...props +}: DynamicTreeViewItemProps) => { + const isLastNode = depth === tree.length - 1; + const styles = useStyles(depth); + const buttonRef = useRef>({}); + + const onKeyboardToggle = () => { + if (!isLastNode) { + onToggleExpand(); + } + onSelect(selectionDepth, aggData.key, tree[depth].type); + }; + + const onButtonToggle = () => { + if (!isLastNode && !isExpanded) { + onToggleExpand(); + } + onSelect(selectionDepth, aggData.key, tree[depth].type); + }; + + const onArrowToggle = (event: MouseEvent) => { + disableEventDefaults(event); + if (!isLastNode) { + onToggleExpand(); + } + }; + + // Enable keyboard navigation + const onKeyDown = (event: React.KeyboardEvent) => { + switch (event.key) { + case keys.ARROW_DOWN: { + focusNextButton(event); + break; + } + case keys.ARROW_UP: { + focusPreviousButton(event); + break; + } + case keys.ARROW_RIGHT: { + if (!isExpanded && !isLastNode) { + disableEventDefaults(event); + onKeyboardToggle(); + } + break; + } + case keys.ARROW_LEFT: { + if (isExpanded) { + disableEventDefaults(event); + onKeyboardToggle(); + } + } + default: + break; + } + }; + + const onChildrenKeydown = (event: React.KeyboardEvent, key: string) => { + if (event.key === keys.ARROW_LEFT) { + disableEventDefaults(event); + buttonRef.current[key].focus(); + } + }; + + const isSelected = useMemo(() => { + return ( + selected === + Object.entries({ ...selectionDepth, [tree[depth].type]: aggData.key }) + .map(([k, v]) => `${k}.${v}`) + .join() + ); + }, [aggData.key, depth, selected, selectionDepth, tree]); + + return ( +
  • + +
    onChildrenKeydown(event, aggData.key.toString())} + > + {!isLastNode && ( + + )} +
    +
  • + ); +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/mocks.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/mocks.ts new file mode 100644 index 0000000000000..e14a1aa73e04b --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/mocks.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const clusterResponseMock = { + buckets: [ + { key: 'awp-demo-gke-main', doc_count: 58645 }, + { key: 'awp-demo-gke-test', doc_count: 23957 }, + ], + hasNextPage: false, +}; + +export const nodeResponseMock = { + buckets: [ + { key: 'default', doc_count: 236 }, + { key: 'kube-system', doc_count: 30360 }, + { key: 'production', doc_count: 30713 }, + { key: 'qa', doc_count: 412 }, + { key: 'staging', doc_count: 220 }, + ], + hasNextPage: false, +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/styles.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/styles.ts new file mode 100644 index 0000000000000..65593a013e7bf --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/styles.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import { CSSObject } from '@emotion/react'; +import { transparentize } from '@elastic/eui'; +import { useEuiTheme } from '../../../hooks'; + +export const useStyles = (depth: number) => { + const { euiTheme } = useEuiTheme(); + + const cached = useMemo(() => { + const { size, colors } = euiTheme; + + const loadMoreButtonWrapper: CSSObject = { + position: 'relative', + textAlign: 'center', + width: `calc(100% + ${depth * 24}px)`, + marginLeft: `-${depth * 24}px`, + '&:after': { + content: `''`, + position: 'absolute', + top: '50%', + width: '100%', + border: `1px dashed ${colors.mediumShade}`, + left: 0, + }, + }; + const loadMoreButton: CSSObject = { + position: 'relative', + cursor: 'pointer', + zIndex: 2, + }; + const loadMoreText: CSSObject = { + marginRight: size.s, + }; + const loadMoreTextLeft: CSSObject = { + marginLeft: size.s, + }; + const labelIcon: CSSObject = { + marginRight: size.s, + marginLeft: size.s, + }; + + const treeViewWrapper = (expanded: boolean): CSSObject => ({ + display: !expanded ? 'none' : 'inherit', + '.euiTreeView__node--selected > .euiTreeView__nodeInner': { + backgroundColor: transparentize(colors.darkestShade, 0.1), + }, + '.euiTreeView__node--expanded': { + maxHeight: '100%', + }, + }); + + return { + loadMoreButton, + loadMoreButtonWrapper, + loadMoreText, + loadMoreTextLeft, + labelIcon, + treeViewWrapper, + }; + }, [euiTheme, depth]); + + return cached; +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/types.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/types.ts new file mode 100644 index 0000000000000..106bc8c2130bd --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/types.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { QueryDslQueryContainerBool, TreeNavSelection, DynamicTree } from '../../../types'; + +export type DynamicTreeViewProps = { + tree: DynamicTree[]; + depth?: number; + selectionDepth?: TreeNavSelection; + query: QueryDslQueryContainerBool; + indexPattern?: string; + onSelect: (selectionDepth: TreeNavSelection, key: string | number, type: string) => void; + hasSelection?: boolean; + 'aria-label': string; + selected?: string; + expanded?: boolean; +}; + +export type DynamicTreeViewItemProps = Required> & { + onToggleExpand: any; + aggData: any; + isExpanded: boolean; +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/helpers.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/helpers.ts new file mode 100644 index 0000000000000..12a77a923c6c3 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/helpers.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { DEFAULT_QUERY } from '../../../common/constants'; +import { KubernetesCollection, QueryDslQueryContainerBool, TreeNavSelection } from '../../types'; + +export const KUBERNETES_COLLECTION_FIELDS = { + [KubernetesCollection.cluster]: 'orchestrator.cluster.name', + [KubernetesCollection.namespace]: 'orchestrator.namespace', + [KubernetesCollection.node]: 'cloud.instance.name', + [KubernetesCollection.pod]: 'orchestrator.resource.name', + [KubernetesCollection.containerImage]: 'container.image.name', +}; + +export const addTreeNavSelectionToFilterQuery = ( + filterQuery: string | undefined, + treeNavSelection: TreeNavSelection +) => { + let validFilterQuery = DEFAULT_QUERY; + + try { + const parsedFilterQuery: QueryDslQueryContainerBool = JSON.parse(filterQuery || '{}'); + if (!(parsedFilterQuery?.bool?.filter && Array.isArray(parsedFilterQuery.bool.filter))) { + throw new Error('Invalid filter query'); + } + parsedFilterQuery.bool.filter.push( + ...Object.keys(treeNavSelection).map((collectionKey) => { + const collection = collectionKey as KubernetesCollection; + return { + bool: { + should: [ + { + match: { + [KUBERNETES_COLLECTION_FIELDS[collection]]: treeNavSelection[collection], + }, + }, + ], + }, + }; + }) + ); + validFilterQuery = JSON.stringify(parsedFilterQuery); + } catch { + // no-op since validFilterQuery is initialized to be DEFAULT_QUERY + } + + return validFilterQuery; +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/index.tsx b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/index.tsx index e934fe4a31f2d..7de0969df8e97 100644 --- a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/index.tsx +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/index.tsx @@ -5,10 +5,13 @@ * 2.0. */ -import React from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { EuiSplitPanel, EuiText } from '@elastic/eui'; import { useStyles } from './styles'; -import type { IndexPattern, GlobalFilter } from '../../types'; +import { IndexPattern, GlobalFilter, TreeNavSelection, KubernetesCollection } from '../../types'; +import { TreeNav } from './tree_nav'; +import { addTreeNavSelectionToFilterQuery } from './helpers'; +import { Breadcrumb } from './breadcrumb'; export interface TreeViewContainerDeps { globalFilter: GlobalFilter; @@ -16,19 +19,41 @@ export interface TreeViewContainerDeps { indexPattern?: IndexPattern; } -export const TreeViewContainer = ({ globalFilter, renderSessionsView }: TreeViewContainerDeps) => { +export const TreeViewContainer = ({ + globalFilter, + renderSessionsView, + indexPattern, +}: TreeViewContainerDeps) => { const styles = useStyles(); - // TODO: combine filterQuery with filters from tree view nav + const [treeNavSelection, setTreeNavSelection] = useState({}); + + const onTreeNavSelect = useCallback((selection: TreeNavSelection) => { + setTreeNavSelection(selection); + }, []); + + const hasSelection = useMemo( + () => !!treeNavSelection[KubernetesCollection.cluster], + [treeNavSelection] + ); return ( -

    Tree view nav panel

    +
    - {renderSessionsView(globalFilter.filterQuery)} + + {hasSelection && + renderSessionsView( + addTreeNavSelectionToFilterQuery(globalFilter.filterQuery, treeNavSelection) + )}
    ); diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/styles.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/styles.ts index c490e5b711889..3aa1f786e8c32 100644 --- a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/styles.ts +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/styles.ts @@ -24,7 +24,7 @@ export const useStyles = () => { }; const treeViewNav: CSSObject = { - width: '284px', + width: '316px', }; const sessionsPanel: CSSObject = { diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/constants.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/constants.ts new file mode 100644 index 0000000000000..b0dd7a66c0473 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/constants.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { KubernetesCollection, DynamicTree } from '../../../types'; +import { KUBERNETES_COLLECTION_FIELDS } from '../helpers'; +import { translations } from './translations'; + +const LOGICAL_TREE_VIEW: DynamicTree[] = [ + { + key: KUBERNETES_COLLECTION_FIELDS.cluster, + iconProps: { type: 'heatmap', color: 'success' }, + type: KubernetesCollection.cluster, + name: translations.cluster(), + namePlural: translations.cluster(true), + }, + { + key: KUBERNETES_COLLECTION_FIELDS.namespace, + iconProps: { type: 'nested', color: 'primary' }, + type: KubernetesCollection.namespace, + name: translations.namespace(), + namePlural: translations.namespace(true), + }, + { + key: KUBERNETES_COLLECTION_FIELDS.pod, + iconProps: { type: 'package', color: 'warning' }, + type: KubernetesCollection.pod, + name: translations.pod(), + namePlural: translations.pod(true), + }, + { + key: KUBERNETES_COLLECTION_FIELDS.containerImage, + iconProps: { type: 'image', color: 'danger' }, + type: KubernetesCollection.containerImage, + name: translations.containerImage(), + namePlural: translations.containerImage(true), + }, +]; + +const INFRASTRUCTURE_TREE_VIEW = LOGICAL_TREE_VIEW.map((tree, index) => { + if (index === 1) { + return { + key: KUBERNETES_COLLECTION_FIELDS.node, + iconProps: { type: 'node', color: 'primary' }, + type: KubernetesCollection.node, + name: translations.node(), + namePlural: translations.node(true), + }; + } + return tree; +}); + +export const TREE_VIEW = { + logical: LOGICAL_TREE_VIEW, + infrastructure: INFRASTRUCTURE_TREE_VIEW, +}; + +export const INFRASTRUCTURE = 'infrastructure'; +export const LOGICAL = 'logical'; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.test.tsx b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.test.tsx new file mode 100644 index 0000000000000..6664acb125f11 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../../test'; +import { TreeNav } from '.'; + +describe('TreeNav component', () => { + let render: () => ReturnType; + let renderResult: ReturnType; + let mockedContext: AppContextTestRender; + + const defaultProps = { + globalFilter: { + startDate: Date.now().toString(), + endDate: (Date.now() + 1).toString(), + }, + onSelect: () => {}, + hasSelection: false, + }; + + beforeEach(() => { + mockedContext = createAppRootMockRenderer(); + }); + + it('mount with Logical View selected by default', async () => { + renderResult = mockedContext.render(); + const elemLabel = await renderResult.getByDisplayValue(/logical/i); + expect(elemLabel).toBeChecked(); + }); + + it('shows the tree path according with the selected view type', async () => { + renderResult = mockedContext.render(); + + const logicalViewPath = 'cluster / namespace / pod / container image'; + const logicViewRadio = await renderResult.getByDisplayValue(/logical/i); + expect(logicViewRadio).toBeChecked(); + expect(renderResult.getByText(logicalViewPath)).toBeInTheDocument(); + + const infraStructureViewRadio = await renderResult.getByDisplayValue(/infrastructure/i); + infraStructureViewRadio.click(); + + expect(renderResult.getByText('cluster / node / pod / container image')).toBeInTheDocument(); + + logicViewRadio.click(); + expect(renderResult.getByText(logicalViewPath)).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.tsx b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.tsx new file mode 100644 index 0000000000000..56ab1c94d93a5 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.tsx @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useState, useMemo } from 'react'; +import { EuiButtonGroup, useGeneratedHtmlId, EuiText, EuiSpacer } from '@elastic/eui'; +import { + TREE_VIEW_INFRASTRUCTURE_VIEW, + TREE_VIEW_LOGICAL_VIEW, + TREE_VIEW_SWITCHER_LEGEND, +} from '../../../../common/translations'; +import { useStyles } from './styles'; +import { IndexPattern, GlobalFilter, TreeNavSelection } from '../../../types'; +import { DynamicTreeView } from '../dynamic_tree_view'; +import { addTimerangeToQuery } from '../../../utils/add_timerange_to_query'; +import { INFRASTRUCTURE, LOGICAL, TREE_VIEW } from './constants'; +import { TreeViewKind, TreeViewOptionsGroup } from './types'; + +interface TreeNavProps { + indexPattern?: IndexPattern; + globalFilter: GlobalFilter; + onSelect: (selection: TreeNavSelection) => void; + hasSelection: boolean; +} + +export const TreeNav = ({ indexPattern, globalFilter, onSelect, hasSelection }: TreeNavProps) => { + const styles = useStyles(); + const [tree, setTree] = useState(TREE_VIEW.logical); + const [selected, setSelected] = useState(''); + + const filterQueryWithTimeRange = useMemo(() => { + return addTimerangeToQuery( + globalFilter.filterQuery, + globalFilter.startDate, + globalFilter.endDate + ); + }, [globalFilter.filterQuery, globalFilter.startDate, globalFilter.endDate]); + + const treeNavTypePrefix = useGeneratedHtmlId({ + prefix: 'treeNavType', + }); + + const logicalTreeViewPrefix = `${treeNavTypePrefix}${LOGICAL}`; + + const [toggleIdSelected, setToggleIdSelected] = useState(logicalTreeViewPrefix); + + const options: TreeViewOptionsGroup[] = [ + { + id: logicalTreeViewPrefix, + label: TREE_VIEW_LOGICAL_VIEW, + value: LOGICAL, + }, + { + id: `${treeNavTypePrefix}${INFRASTRUCTURE}`, + label: TREE_VIEW_INFRASTRUCTURE_VIEW, + value: INFRASTRUCTURE, + }, + ]; + + const handleTreeViewSwitch = (id: string, value: TreeViewKind) => { + setToggleIdSelected(id); + setTree(TREE_VIEW[value]); + }; + + return ( + <> + + + + {tree.map((t) => t.name).join(' / ')} + + +
    + { + const newSelectionDepth = { + ...selectionDepth, + [type]: key, + }; + setSelected( + Object.entries(newSelectionDepth) + .map(([k, v]) => `${k}.${v}`) + .join() + ); + onSelect(newSelectionDepth); + }} + hasSelection={hasSelection} + /> +
    + + ); +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/styles.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/styles.ts new file mode 100644 index 0000000000000..27bab04d90511 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/styles.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import { CSSObject } from '@emotion/react'; +import { useEuiTheme } from '../../../hooks'; + +export const useStyles = () => { + const { euiTheme } = useEuiTheme(); + + const cached = useMemo(() => { + const { size } = euiTheme; + + const treeViewSwitcher: CSSObject = { + '.euiButton__text': { + fontSize: size.m, + }, + }; + + const treeViewContainer: CSSObject = { + height: '600px', + overflowY: 'auto', + }; + + const treeViewLegend: CSSObject = { + textTransform: 'capitalize', + }; + + return { + treeViewSwitcher, + treeViewContainer, + treeViewLegend, + }; + }, [euiTheme]); + + return cached; +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/translations.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/translations.ts new file mode 100644 index 0000000000000..d020b3ae64a24 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/translations.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +const TREE_NAV_CLUSTER = (isPlural = false) => + i18n.translate('xpack.kubernetesSecurity.treeNav.cluster', { + defaultMessage: '{isPlural, plural, =true {clusters} other {cluster}}', + values: { isPlural }, + }); +const TREE_NAV_NAMESPACE = (isPlural = false) => + i18n.translate('xpack.kubernetesSecurity.treeNav.namespace', { + defaultMessage: '{isPlural, plural, =true {namespaces} other {namespace}}', + values: { isPlural }, + }); +const TREE_NAV_POD = (isPlural = false) => + i18n.translate('xpack.kubernetesSecurity.treeNav.pod', { + defaultMessage: '{isPlural, plural, =true {pods} other {pod}}', + values: { isPlural }, + }); +const TREE_NAV_CONTAINER_IMAGE = (isPlural = false) => + i18n.translate('xpack.kubernetesSecurity.treeNav.containerImage', { + defaultMessage: '{isPlural, plural, =true {container images} other { container image}}', + values: { isPlural }, + }); +const TREE_NAV_NODE = (isPlural = false) => + i18n.translate('xpack.kubernetesSecurity.treeNav.node', { + defaultMessage: '{isPlural, plural, =true {nodes} other {node}}', + values: { isPlural }, + }); + +export const translations = { + cluster: TREE_NAV_CLUSTER, + namespace: TREE_NAV_NAMESPACE, + pod: TREE_NAV_POD, + containerImage: TREE_NAV_CONTAINER_IMAGE, + node: TREE_NAV_NODE, +}; diff --git a/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/types.ts b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/types.ts new file mode 100644 index 0000000000000..0643f84e26119 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/types.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type TreeViewKind = 'infrastructure' | 'logical'; + +export interface TreeViewOptionsGroup { + id: string; + label: string; + value: TreeViewKind; +} diff --git a/x-pack/plugins/kubernetes_security/public/components/widgets_toggle/index.test.tsx b/x-pack/plugins/kubernetes_security/public/components/widgets_toggle/index.test.tsx deleted file mode 100644 index cb2db24d28faf..0000000000000 --- a/x-pack/plugins/kubernetes_security/public/components/widgets_toggle/index.test.tsx +++ /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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; -import { WIDGET_TOGGLE_SHOW, WIDGET_TOGGLE_HIDE } from '../../../common/translations'; -import { WidgetsToggle, TOGGLE_TEST_ID } from '.'; - -describe('WidgetsToggle component', () => { - let render: () => ReturnType; - let renderResult: ReturnType; - let mockedContext: AppContextTestRender; - const handleToggleHideWidgets = jest.fn(); - - beforeEach(() => { - mockedContext = createAppRootMockRenderer(); - }); - - describe('When PercentWidget is mounted', () => { - it('show "hide widgets" text when shouldHideWidgets is false', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.getByText(WIDGET_TOGGLE_HIDE)).toBeVisible(); - }); - it('show "show widgets" text when shouldHideWidgets is true', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.getByText(WIDGET_TOGGLE_SHOW)).toBeVisible(); - }); - it('shouldHideWidgets defaults to false when not provided', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.getByText(WIDGET_TOGGLE_HIDE)).toBeVisible(); - }); - it('clicking the toggle fires the callback', async () => { - renderResult = mockedContext.render( - - ); - - renderResult.queryByTestId(TOGGLE_TEST_ID)?.click(); - expect(handleToggleHideWidgets).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/x-pack/plugins/kubernetes_security/public/components/widgets_toggle/index.tsx b/x-pack/plugins/kubernetes_security/public/components/widgets_toggle/index.tsx deleted file mode 100644 index 5a31b8504f8ab..0000000000000 --- a/x-pack/plugins/kubernetes_security/public/components/widgets_toggle/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React from 'react'; -import { EuiButtonEmpty } from '@elastic/eui'; -import { WIDGET_TOGGLE_SHOW, WIDGET_TOGGLE_HIDE } from '../../../common/translations'; - -export const TOGGLE_TEST_ID = 'kubernetesSecurity:widgetToggle'; - -interface WidgetsToggleDeps { - handleToggleHideWidgets: () => void; - shouldHideWidgets?: boolean; -} - -export const WidgetsToggle = ({ - handleToggleHideWidgets, - shouldHideWidgets = false, -}: WidgetsToggleDeps) => ( - - {shouldHideWidgets ? WIDGET_TOGGLE_SHOW : WIDGET_TOGGLE_HIDE} - -); diff --git a/x-pack/plugins/kubernetes_security/public/hooks/index.ts b/x-pack/plugins/kubernetes_security/public/hooks/index.ts index 14d956be9b629..2e330dfb1b159 100644 --- a/x-pack/plugins/kubernetes_security/public/hooks/index.ts +++ b/x-pack/plugins/kubernetes_security/public/hooks/index.ts @@ -8,3 +8,4 @@ export { useEuiTheme } from './use_eui_theme'; export { useSetFilter } from './use_filter'; export { useLastUpdated } from './use_last_updated'; +export { useScroll } from './use_scroll'; diff --git a/x-pack/plugins/kubernetes_security/public/hooks/use_scroll.ts b/x-pack/plugins/kubernetes_security/public/hooks/use_scroll.ts new file mode 100644 index 0000000000000..716e35dbb0987 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/hooks/use_scroll.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEffect } from 'react'; +import _ from 'lodash'; + +const SCROLL_END_BUFFER_HEIGHT = 20; +const DEBOUNCE_TIMEOUT = 500; + +function getScrollPosition(div: HTMLElement) { + if (div) { + return div.scrollTop; + } else { + return document.documentElement.scrollTop || document.body.scrollTop; + } +} + +interface IUseScrollDeps { + div: HTMLElement | null; + handler(pos: number, endReached: boolean): void; +} + +/** + * listens to scroll events on given div, if scroll reaches bottom, calls a callback + * @param {ref} ref to listen to scroll events on + * @param {function} handler function receives params (scrollTop, endReached) + */ +export function useScroll({ div, handler }: IUseScrollDeps) { + useEffect(() => { + if (div) { + const debounced = _.debounce(() => { + const pos = getScrollPosition(div); + const endReached = pos + div.offsetHeight > div.scrollHeight - SCROLL_END_BUFFER_HEIGHT; + + handler(pos, endReached); + }, DEBOUNCE_TIMEOUT); + + div.onscroll = debounced; + + return () => { + debounced.cancel(); + + div.onscroll = null; + }; + } + }, [div, handler]); +} diff --git a/x-pack/plugins/kubernetes_security/public/methods/index.tsx b/x-pack/plugins/kubernetes_security/public/methods/index.tsx index 85316f74b04f6..f0a140a612705 100644 --- a/x-pack/plugins/kubernetes_security/public/methods/index.tsx +++ b/x-pack/plugins/kubernetes_security/public/methods/index.tsx @@ -11,7 +11,15 @@ import { QueryClient, QueryClientProvider } from 'react-query'; import { KubernetesSecurityDeps } from '../types'; // Initializing react-query -const queryClient = new QueryClient(); +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, + refetchOnMount: false, + refetchOnReconnect: false, + }, + }, +}); const KubernetesSecurityLazy = lazy(() => import('../components/kubernetes_security_routes')); diff --git a/x-pack/plugins/kubernetes_security/public/types.ts b/x-pack/plugins/kubernetes_security/public/types.ts index 5a41e72d89d89..873c3783be781 100644 --- a/x-pack/plugins/kubernetes_security/public/types.ts +++ b/x-pack/plugins/kubernetes_security/public/types.ts @@ -11,6 +11,7 @@ import type { FieldSpec } from '@kbn/data-plugin/common'; import type { TimelinesUIStart } from '@kbn/timelines-plugin/public'; import type { SessionViewStart } from '@kbn/session-view-plugin/public'; import { BoolQuery } from '@kbn/es-query'; +import { EuiIconProps } from '@elastic/eui'; export interface StartPlugins { data: DataPublicPluginStart; @@ -45,3 +46,27 @@ export interface KubernetesSecurityStart { export type QueryDslQueryContainerBool = { bool: BoolQuery; }; + +export enum KubernetesCollection { + cluster = 'cluster', + namespace = 'namespace', + node = 'node', + pod = 'pod', + containerImage = 'containerImage', +} + +export interface TreeNavSelection { + [KubernetesCollection.cluster]?: string; + [KubernetesCollection.namespace]?: string; + [KubernetesCollection.node]?: string; + [KubernetesCollection.pod]?: string; + [KubernetesCollection.containerImage]?: string; +} + +export type DynamicTree = { + key: string; + type: KubernetesCollection; + iconProps: EuiIconProps; + name: string; + namePlural: string; +}; diff --git a/x-pack/plugins/kubernetes_security/public/utils/add_commas_to_number.test.ts b/x-pack/plugins/kubernetes_security/public/utils/add_commas_to_number.test.ts new file mode 100644 index 0000000000000..03faf16921c1b --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/utils/add_commas_to_number.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { addCommasToNumber } from './add_commas_to_number'; + +describe('addCommasToNumber(num)', () => { + it('works for a number without needing a comma', () => { + expect(addCommasToNumber(123)).toEqual('123'); + }); + it('works for a number that needs a comma', () => { + expect(addCommasToNumber(1234)).toEqual('1,234'); + }); + it('works for a number that needs multiple commas', () => { + expect(addCommasToNumber(123456789)).toEqual('123,456,789'); + }); + it('works for negative number', () => { + expect(addCommasToNumber(-10)).toEqual('-10'); + }); + it('works for negative number with commas', () => { + expect(addCommasToNumber(-10000)).toEqual('-10,000'); + }); + it('works for NaN', () => { + expect(addCommasToNumber(NaN)).toEqual('NaN'); + }); + it('works for Infinity', () => { + expect(addCommasToNumber(Infinity)).toEqual('Infinity'); + }); + it('works for zero', () => { + expect(addCommasToNumber(0)).toEqual('0'); + }); +}); diff --git a/x-pack/plugins/kubernetes_security/public/utils/add_commas_to_number.ts b/x-pack/plugins/kubernetes_security/public/utils/add_commas_to_number.ts new file mode 100644 index 0000000000000..3e440ab8c9226 --- /dev/null +++ b/x-pack/plugins/kubernetes_security/public/utils/add_commas_to_number.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. + */ + +/** + * Add commas as thousands separators to a number. + * + * @param {Number} num + * @return {String} num in string with commas as thousands separaters + */ +export function addCommasToNumber(num: number) { + return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); +} diff --git a/x-pack/plugins/kubernetes_security/server/routes/aggregate.ts b/x-pack/plugins/kubernetes_security/server/routes/aggregate.ts index 252b20a458a78..e56a17d89845f 100644 --- a/x-pack/plugins/kubernetes_security/server/routes/aggregate.ts +++ b/x-pack/plugins/kubernetes_security/server/routes/aggregate.ts @@ -14,6 +14,7 @@ import { AGGREGATE_PAGE_SIZE, AGGREGATE_MAX_BUCKETS, } from '../../common/constants'; +import { AggregateBucketPaginationResult } from '../../common/types/aggregate'; // sort by values const ASC = 'asc'; @@ -29,6 +30,7 @@ export const registerAggregateRoute = (router: IRouter) => { countBy: schema.maybe(schema.string()), groupBy: schema.string(), page: schema.number(), + perPage: schema.maybe(schema.number()), index: schema.maybe(schema.string()), sortByCount: schema.maybe(schema.string()), }), @@ -36,10 +38,19 @@ export const registerAggregateRoute = (router: IRouter) => { }, async (context, request, response) => { const client = (await context.core).elasticsearch.client.asCurrentUser; - const { query, countBy, sortByCount, groupBy, page, index } = request.query; + const { query, countBy, sortByCount, groupBy, page, perPage, index } = request.query; try { - const body = await doSearch(client, query, groupBy, page, index, countBy, sortByCount); + const body = await doSearch( + client, + query, + groupBy, + page, + perPage, + index, + countBy, + sortByCount + ); return response.ok({ body }); } catch (err) { @@ -54,10 +65,11 @@ export const doSearch = async ( query: string, groupBy: string, page: number, // zero based + perPage = AGGREGATE_PAGE_SIZE, index?: string, countBy?: string, sortByCount?: string -) => { +): Promise => { const queryDSL = JSON.parse(query); const countByAggs = countBy @@ -91,8 +103,8 @@ export const doSearch = async ( bucket_sort: { bucket_sort: { sort: [sort], // defaulting to alphabetic sort - size: AGGREGATE_PAGE_SIZE, - from: AGGREGATE_PAGE_SIZE * page, + size: perPage + 1, // check if there's a "next page" + from: perPage * page, }, }, }, @@ -102,6 +114,16 @@ export const doSearch = async ( }); const agg: any = search.aggregations?.custom_agg; + const buckets = agg?.buckets || []; - return agg?.buckets || []; + const hasNextPage = buckets.length > perPage; + + if (hasNextPage) { + buckets.pop(); + } + + return { + buckets, + hasNextPage, + }; }; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx index a12578c66b0c9..16bc0814a9916 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx @@ -11,6 +11,7 @@ import React, { useMemo, memo, useContext, useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiPopover, EuiButtonIcon, EuiContextMenuPanel, EuiContextMenuItem } from '@elastic/eui'; import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; +import { Easteregg } from './easteregg'; import { NativeRenderer } from '../../native_renderer'; import { DragContext, DragDropIdentifier } from '../../drag_drop'; import { StateSetter, DatasourceDataPanelProps, DatasourceMap } from '../../types'; @@ -97,6 +98,7 @@ export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => { return ( <> + {Object.keys(props.datasourceMap).length > 1 && ( { + let handle: number = 0; + function tick() { + handle = requestAnimationFrame(() => { + setPosition(({ top, left, vX, vY }) => { + let newVx = vX + Math.random() * 0.5 - 0.25; + let newVy = vY + Math.random() - 0.5; + if (top < 50) { + newVy = Math.abs(newVy); + } + if (top > window.innerHeight - 300) { + newVy = -1 * Math.abs(newVy); + } + if (left < 50) { + newVx = Math.abs(newVx); + } + if (left > window.innerWidth - 300) { + newVx = -1 * Math.abs(newVx); + } + + return { + top: top + vY, + left: left + vX, + vX: newVx, + vY: newVy, + }; + }); + tick(); + }); + } + tick(); + return () => { + cancelAnimationFrame(handle); + }; + }, []); + + return ( + ELK-Bee 0 ? 'scale(-1, 1)' : undefined, + top: position.top, + left: position.left, + zIndex: 999, + }} + /> + ); +} + +// eslint-disable-next-line import/no-default-export +export default Bee; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/easteregg/elastic_elk_b.png b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/easteregg/elastic_elk_b.png new file mode 100644 index 0000000000000..077ee2fc24eec Binary files /dev/null and b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/easteregg/elastic_elk_b.png differ diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/easteregg/index.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/easteregg/index.tsx new file mode 100644 index 0000000000000..7bfd7c666079a --- /dev/null +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/easteregg/index.tsx @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import type { Query } from '@kbn/es-query'; +import { EuiErrorBoundary } from '@elastic/eui'; + +const Bee = React.lazy(() => import('./bee')); + +const ELK_BEE_REGEX = /^What\'s (an|(\d+)) elk bees?\?$/; + +function Bees({ query }: { query?: Query }) { + if (!query || typeof query !== 'object' || typeof query.query !== 'string') { + return null; + } + const match = ELK_BEE_REGEX.exec(query.query); + if (!match) { + return null; + } + let amount = parseInt(match[2] || '1', 10); + if (isNaN(amount)) { + amount = 0; + } + amount = Math.max(1, Math.min(50, amount)); + return ( + + {new Array(amount).fill(undefined).map((v, i) => ( + + ))} + + ); +} + +export function Easteregg(props: { query?: Query }) { + return ( + // Do not break Lens for an easteregg + + + + ); +} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.test.tsx index c94d7d05828d8..873b96b311a04 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.test.tsx @@ -39,16 +39,16 @@ describe('Values', () => { expect(onChangeSpy.mock.calls[0][0]).toBe(7); }); - it('should not run onChange function on update when value is out of 1-1000 range', () => { + it('should not run onChange function on update when value is out of 1-10000 range', () => { const onChangeSpy = jest.fn(); const instance = shallow(); act(() => { - instance.find(EuiFieldNumber).simulate('change', { currentTarget: { value: '1007' } }); + instance.find(EuiFieldNumber).simulate('change', { currentTarget: { value: '10007' } }); }); instance.update(); - expect(instance.find(EuiFieldNumber).prop('value')).toEqual('1007'); + expect(instance.find(EuiFieldNumber).prop('value')).toEqual('10007'); expect(onChangeSpy.mock.calls.length).toBe(1); - expect(onChangeSpy.mock.calls[0][0]).toBe(1000); + expect(onChangeSpy.mock.calls[0][0]).toBe(10000); }); it('should show an error message when the value is out of bounds', () => { @@ -60,7 +60,7 @@ describe('Values', () => { ); act(() => { - instance.find(EuiFieldNumber).simulate('change', { currentTarget: { value: '1007' } }); + instance.find(EuiFieldNumber).simulate('change', { currentTarget: { value: '10007' } }); }); instance.update(); @@ -91,10 +91,10 @@ describe('Values', () => { expect(instance.find(EuiFieldNumber).prop('isInvalid')).toBeFalsy(); expect(instance.find(EuiFieldNumber).prop('value')).toBe('1'); - changeAndBlur('5000'); + changeAndBlur('50000'); expect(instance.find(EuiFieldNumber).prop('isInvalid')).toBeFalsy(); - expect(instance.find(EuiFieldNumber).prop('value')).toBe('1000'); + expect(instance.find(EuiFieldNumber).prop('value')).toBe('10000'); changeAndBlur(''); // as we're not handling the onChange state, it fallbacks to the value prop diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx index b244bdd54aad3..9e86ea8525adc 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx @@ -14,7 +14,7 @@ export const ValuesInput = ({ value, onChange, minValue = 1, - maxValue = 1000, + maxValue = 10000, label = i18n.translate('xpack.lens.indexPattern.terms.size', { defaultMessage: 'Number of values', }), diff --git a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap index 43f4082d00dbe..66162b0bee018 100644 --- a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap +++ b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap @@ -36,9 +36,6 @@ Object { "{\\"b\\":\\"col_b\\",\\"c\\":\\"col_c\\",\\"d\\":\\"col_d\\"}", ], "decorations": Array [], - "hide": Array [ - false, - ], "isHistogram": Array [ false, ], @@ -67,6 +64,9 @@ Object { "seriesType": Array [ "area", ], + "simpleView": Array [ + false, + ], "splitAccessors": Array [ "d", ], diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index 36c00ed55e743..6c06891f530e0 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -83,10 +83,10 @@ export const toExpression = ( }; const simplifiedLayerExpression = { - [layerTypes.DATA]: (layer: XYDataLayerConfig) => ({ ...layer, hide: true }), + [layerTypes.DATA]: (layer: XYDataLayerConfig) => ({ ...layer, simpleView: true }), [layerTypes.REFERENCELINE]: (layer: XYReferenceLineLayerConfig) => ({ ...layer, - hide: true, + simpleView: true, yConfig: layer.yConfig?.map(({ ...rest }) => ({ ...rest, lineWidth: 1, @@ -96,7 +96,7 @@ const simplifiedLayerExpression = { }), [layerTypes.ANNOTATIONS]: (layer: XYAnnotationLayerConfig) => ({ ...layer, - hide: true, + simpleView: true, }), }; @@ -411,7 +411,7 @@ const annotationLayerToExpression = ( type: 'function', function: 'extendedAnnotationLayer', arguments: { - hide: [Boolean(layer.hide)], + simpleView: [Boolean(layer.simpleView)], layerId: [layer.layerId], annotations: layer.annotations ? layer.annotations.map((ann): Ast => eventAnnotationService.toExpression(ann)) @@ -455,7 +455,7 @@ const dataLayerToExpression = ( function: 'extendedDataLayer', arguments: { layerId: [layer.layerId], - hide: [Boolean(layer.hide)], + simpleView: [Boolean(layer.simpleView)], xAccessor: layer.xAccessor ? [layer.xAccessor] : [], xScaleType: [getScaleType(metadata[layer.layerId][layer.xAccessor], ScaleType.Linear)], isHistogram: [isHistogramDimension], diff --git a/x-pack/plugins/lens/public/xy_visualization/types.ts b/x-pack/plugins/lens/public/xy_visualization/types.ts index 0beda9f4740ac..58c4cfb7e26c4 100644 --- a/x-pack/plugins/lens/public/xy_visualization/types.ts +++ b/x-pack/plugins/lens/public/xy_visualization/types.ts @@ -92,7 +92,7 @@ export interface XYDataLayerConfig { layerType: 'data'; seriesType: SeriesType; xAccessor?: string; - hide?: boolean; + simpleView?: boolean; yConfig?: YConfig[]; splitAccessor?: string; palette?: PaletteOutput; @@ -113,7 +113,7 @@ export interface XYAnnotationLayerConfig { layerId: string; layerType: 'annotations'; annotations: EventAnnotationConfig[]; - hide?: boolean; + simpleView?: boolean; } export type XYLayerConfig = diff --git a/x-pack/plugins/maps/common/elasticsearch_util/spatial_filter_utils.test.ts b/x-pack/plugins/maps/common/elasticsearch_util/spatial_filter_utils.test.ts index 723862da09196..e0b63dd94db34 100644 --- a/x-pack/plugins/maps/common/elasticsearch_util/spatial_filter_utils.test.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/spatial_filter_utils.test.ts @@ -30,6 +30,7 @@ describe('createExtentFilter', () => { disabled: false, key: 'location', negate: false, + type: 'spatial_filter', }, query: { bool: { @@ -66,6 +67,7 @@ describe('createExtentFilter', () => { disabled: false, key: 'location', negate: false, + type: 'spatial_filter', }, query: { bool: { @@ -102,6 +104,7 @@ describe('createExtentFilter', () => { disabled: false, key: 'location', negate: false, + type: 'spatial_filter', }, query: { bool: { @@ -138,6 +141,7 @@ describe('createExtentFilter', () => { disabled: false, key: 'location', negate: false, + type: 'spatial_filter', }, query: { bool: { @@ -174,6 +178,7 @@ describe('createExtentFilter', () => { disabled: false, key: 'location', negate: false, + type: 'spatial_filter', }, query: { bool: { @@ -210,6 +215,7 @@ describe('createExtentFilter', () => { disabled: false, isMultiIndex: true, negate: false, + type: 'spatial_filter', }, query: { bool: { diff --git a/x-pack/plugins/maps/common/elasticsearch_util/spatial_filter_utils.ts b/x-pack/plugins/maps/common/elasticsearch_util/spatial_filter_utils.ts index 1cf19a0c8aa81..faa4fbc1383ee 100644 --- a/x-pack/plugins/maps/common/elasticsearch_util/spatial_filter_utils.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/spatial_filter_utils.ts @@ -89,6 +89,7 @@ export function createExtentFilter(mapExtent: MapExtent, geoFieldNames: string[] } const meta: FilterMeta = { + type: SPATIAL_FILTER_TYPE, alias: null, disabled: false, negate: false, diff --git a/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.ts b/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.tsx similarity index 97% rename from x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.ts rename to x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.tsx index 05009abc7793b..bedf997566ec2 100644 --- a/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/ems_vector_tile_layer/ems_vector_tile_layer.tsx @@ -5,13 +5,15 @@ * 2.0. */ +import React from 'react'; import type { Map as MbMap, LayerSpecification, StyleSpecification } from '@kbn/mapbox-gl'; import { type blendMode, type EmsSpriteSheet, TMSService } from '@elastic/ems-client'; import { i18n } from '@kbn/i18n'; import _ from 'lodash'; +import { EuiIcon } from '@elastic/eui'; // @ts-expect-error import { RGBAImage } from './image_utils'; -import { AbstractLayer } from '../layer'; +import { AbstractLayer, type LayerIcon } from '../layer'; import { AUTOSELECT_EMS_LOCALE, NO_EMS_LOCALE, @@ -486,6 +488,15 @@ export class EmsVectorTileLayer extends AbstractLayer { return 'grid'; } + getLayerIcon(): LayerIcon { + return { + icon: , + tooltipContent: i18n.translate('xpack.maps.emsVectorTileLayer.layerDescription', { + defaultMessage: `Reference map provided by Elastic Maps Service (EMS).`, + }), + }; + } + isBasemap(order: number) { return order === 0; } diff --git a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.tsx b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.tsx index 6874820d561f7..cc094bc6caeef 100644 --- a/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/ems_tms_source/ems_tms_source.tsx @@ -66,7 +66,7 @@ export class EMSTMSSource extends AbstractSource implements ITMSSource { } async getImmutableProperties() { - const displayName = await this.getDisplayName(); + const tileServiceName = await this._getTileServiceName(); const autoSelectMsg = i18n.translate('xpack.maps.source.emsTile.isAutoSelectLabel', { defaultMessage: 'autoselect based on Kibana theme', }); @@ -80,7 +80,9 @@ export class EMSTMSSource extends AbstractSource implements ITMSSource { label: i18n.translate('xpack.maps.source.emsTile.serviceId', { defaultMessage: `Tile service`, }), - value: this._descriptor.isAutoSelect ? `${displayName} - ${autoSelectMsg}` : displayName, + value: this._descriptor.isAutoSelect + ? `${tileServiceName} - ${autoSelectMsg}` + : tileServiceName, }, ]; @@ -114,6 +116,12 @@ export class EMSTMSSource extends AbstractSource implements ITMSSource { } async getDisplayName() { + return i18n.translate('xpack.maps.source.emsTile.basemapLabel', { + defaultMessage: 'Basemap', + }); + } + + async _getTileServiceName() { try { const emsTMSService = await this._getEMSTMSService(); return emsTMSService.getDisplayName(); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts index 831dc90871dff..a7afbbd7e85eb 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -224,6 +224,7 @@ describe('ESGeoGridSource', () => { disabled: false, key: 'bar', negate: false, + type: 'spatial_filter', }, query: { bool: { diff --git a/x-pack/plugins/maps/public/embeddable/get_geo_fields_label.test.ts b/x-pack/plugins/maps/public/embeddable/get_geo_fields_label.test.ts new file mode 100644 index 0000000000000..5144e87e8b698 --- /dev/null +++ b/x-pack/plugins/maps/public/embeddable/get_geo_fields_label.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getGeoFieldsLabel } from './get_geo_fields_label'; + +test('single field', () => { + expect(getGeoFieldsLabel(['location'])).toEqual('location'); +}); + +test('two fields', () => { + expect(getGeoFieldsLabel(['location', 'secondLocation'])).toEqual('location and secondLocation'); +}); + +test('three or more fields', () => { + expect(getGeoFieldsLabel(['location', 'secondLocation', 'thirdLocation'])).toEqual( + 'location, secondLocation, and thirdLocation' + ); +}); diff --git a/x-pack/plugins/maps/public/embeddable/get_geo_fields_label.ts b/x-pack/plugins/maps/public/embeddable/get_geo_fields_label.ts new file mode 100644 index 0000000000000..dba2776720aad --- /dev/null +++ b/x-pack/plugins/maps/public/embeddable/get_geo_fields_label.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export function getGeoFieldsLabel(geoFieldNames: string[]) { + if (geoFieldNames.length === 0) { + return ''; + } + + if (geoFieldNames.length === 1) { + return geoFieldNames[0]; + } + + const connector = i18n.translate('xpack.maps.embeddable.geoFieldsConnector', { + defaultMessage: ' and ', + }); + + if (geoFieldNames.length === 2) { + return geoFieldNames[0] + connector + geoFieldNames[1]; + } + + return ( + geoFieldNames.slice(0, geoFieldNames.length - 1).join(', ') + + ',' + + connector + + geoFieldNames[geoFieldNames.length - 1] + ); +} diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index 8a1064a8725bb..59f679d041024 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -82,8 +82,8 @@ import { getIndexPatternsFromIds } from '../index_pattern_util'; import { getMapAttributeService } from '../map_attribute_service'; import { isUrlDrilldown, toValueClickDataFormat } from '../trigger_actions/trigger_utils'; import { waitUntilTimeLayersLoad$ } from '../routes/map_page/map_app/wait_until_time_layers_load'; -import { synchronizeMovement } from './synchronize_movement'; -import { getFilterByMapExtent } from '../trigger_actions/filter_by_map_extent_action'; +import { mapEmbeddablesSingleton } from './map_embeddables_singleton'; +import { getGeoFieldsLabel } from './get_geo_fields_label'; import { MapByValueInput, @@ -112,7 +112,6 @@ export class MapEmbeddable private _savedMap: SavedMap; private _renderTooltipContent?: RenderToolTipContent; private _subscription: Subscription; - private _prevFilterByMapExtent: boolean; private _prevIsRestore: boolean = false; private _prevMapExtent?: MapExtent; private _prevTimeRange?: TimeRange; @@ -144,7 +143,6 @@ export class MapEmbeddable this._initializeSaveMap(); this._subscription = this.getUpdated$().subscribe(() => this.onUpdate()); this._controlledBy = `mapEmbeddablePanel${this.id}`; - this._prevFilterByMapExtent = getFilterByMapExtent(this.input); } public reportsEmbeddableLoad() { @@ -278,16 +276,6 @@ export class MapEmbeddable } onUpdate() { - const filterByMapExtent = getFilterByMapExtent(this.input); - if (this._prevFilterByMapExtent !== filterByMapExtent) { - this._prevFilterByMapExtent = filterByMapExtent; - if (filterByMapExtent) { - this.setMapExtentFilter(); - } else { - this.clearMapExtentFilter(); - } - } - if ( !_.isEqual(this.input.timeRange, this._prevTimeRange) || !_.isEqual(this.input.query, this._prevQuery) || @@ -321,8 +309,12 @@ export class MapEmbeddable : this.input.isMovementSynchronized; }; + _getIsFilterByMapExtent = () => { + return this.input.filterByMapExtent === undefined ? false : this.input.filterByMapExtent; + }; + _gotoSynchronizedLocation() { - const syncedLocation = synchronizeMovement.getLocation(); + const syncedLocation = mapEmbeddablesSingleton.getLocation(); if (syncedLocation) { // set map to synchronized view this._mapSyncHandler(syncedLocation.lat, syncedLocation.lon, syncedLocation.zoom); @@ -334,7 +326,7 @@ export class MapEmbeddable // Use goto because un-rendered map will not have accurate mapCenter and mapZoom. const goto = getGoto(this._savedMap.getStore().getState()); if (goto && goto.center) { - synchronizeMovement.setLocation( + mapEmbeddablesSingleton.setLocation( this.input.id, goto.center.lat, goto.center.lon, @@ -347,12 +339,12 @@ export class MapEmbeddable // Initialize synchronized view to map's view const center = getMapCenter(this._savedMap.getStore().getState()); const zoom = getMapZoom(this._savedMap.getStore().getState()); - synchronizeMovement.setLocation(this.input.id, center.lat, center.lon, zoom); + mapEmbeddablesSingleton.setLocation(this.input.id, center.lat, center.lon, zoom); } _propogateMapMovement = (lat: number, lon: number, zoom: number) => { if (this._getIsMovementSynchronized()) { - synchronizeMovement.setLocation(this.input.id, lat, lon, zoom); + mapEmbeddablesSingleton.setLocation(this.input.id, lat, lon, zoom); } }; @@ -418,7 +410,7 @@ export class MapEmbeddable return; } - synchronizeMovement.register(this.input.id, { + mapEmbeddablesSingleton.register(this.input.id, { getTitle: () => { const output = this.getOutput(); if (output.title) { @@ -442,6 +434,18 @@ export class MapEmbeddable this._savedMap.getStore().dispatch(setMapSettings({ autoFitToDataBounds: true })); } }, + getIsFilterByMapExtent: this._getIsFilterByMapExtent, + setIsFilterByMapExtent: (isFilterByMapExtent: boolean) => { + this.updateInput({ filterByMapExtent: isFilterByMapExtent }); + if (isFilterByMapExtent) { + this._setMapExtentFilter(); + } else { + this._clearMapExtentFilter(); + } + }, + getGeoFieldNames: () => { + return getGeoFieldNames(this._savedMap.getStore().getState()); + }, }); if (this._getIsMovementSynchronized()) { this._gotoSynchronizedLocation(); @@ -568,14 +572,21 @@ export class MapEmbeddable } as ActionExecutionContext; }; - setMapExtentFilter() { - const state = this._savedMap.getStore().getState(); - const mapExtent = getMapExtent(state); - const geoFieldNames = getGeoFieldNames(state); - const center = getMapCenter(state); - const zoom = getMapZoom(state); + // Timing bug for dashboard with multiple maps with synchronized movement and filter by map extent enabled + // When moving map with filterByMapExtent:false, previous map extent filter(s) does not get removed + // Cuased by syncDashboardContainerInput applyContainerChangesToState. + // 1) _setMapExtentFilter executes ACTION_GLOBAL_APPLY_FILTER action, + // removing previous map extent filter and adding new map extent filter + // 2) applyContainerChangesToState then re-adds stale input.filters (which contains previous map extent filter) + // Add debounce to fix timing issue. + // 1) applyContainerChangesToState now runs first and does its thing + // 2) _setMapExtentFilter executes ACTION_GLOBAL_APPLY_FILTER action, + // removing previous map extent filter and adding new map extent filter + _setMapExtentFilter = _.debounce(() => { + const mapExtent = getMapExtent(this._savedMap.getStore().getState()); + const geoFieldNames = mapEmbeddablesSingleton.getGeoFieldNames(); - if (center === undefined || mapExtent === undefined || geoFieldNames.length === 0) { + if (mapExtent === undefined || geoFieldNames.length === 0) { return; } @@ -584,12 +595,8 @@ export class MapEmbeddable const mapExtentFilter = createExtentFilter(mapExtent, geoFieldNames); mapExtentFilter.meta.controlledBy = this._controlledBy; mapExtentFilter.meta.alias = i18n.translate('xpack.maps.embeddable.boundsFilterLabel', { - defaultMessage: 'Map bounds at center: {lat}, {lon}, zoom: {zoom}', - values: { - lat: center.lat, - lon: center.lon, - zoom, - }, + defaultMessage: '{geoFieldsLabel} within map bounds', + values: { geoFieldsLabel: getGeoFieldsLabel(geoFieldNames) }, }); const executeContext = { @@ -602,9 +609,9 @@ export class MapEmbeddable throw new Error('Unable to apply map extent filter, could not locate action'); } action.execute(executeContext); - } + }, 100); - clearMapExtentFilter() { + _clearMapExtentFilter() { this._prevMapExtent = undefined; const executeContext = { ...this.getActionContext(), @@ -620,7 +627,7 @@ export class MapEmbeddable destroy() { super.destroy(); - synchronizeMovement.unregister(this.input.id); + mapEmbeddablesSingleton.unregister(this.input.id); this._isActive = false; if (this._unsubscribeFromStore) { this._unsubscribeFromStore(); @@ -665,8 +672,8 @@ export class MapEmbeddable } const mapExtent = getMapExtent(this._savedMap.getStore().getState()); - if (getFilterByMapExtent(this.input) && !_.isEqual(this._prevMapExtent, mapExtent)) { - this.setMapExtentFilter(); + if (this._getIsFilterByMapExtent() && !_.isEqual(this._prevMapExtent, mapExtent)) { + this._setMapExtentFilter(); } const center = getMapCenter(this._savedMap.getStore().getState()); diff --git a/x-pack/plugins/maps/public/embeddable/synchronize_movement.ts b/x-pack/plugins/maps/public/embeddable/map_embeddables_singleton.ts similarity index 84% rename from x-pack/plugins/maps/public/embeddable/synchronize_movement.ts rename to x-pack/plugins/maps/public/embeddable/map_embeddables_singleton.ts index c1e738224b031..253006924ee88 100644 --- a/x-pack/plugins/maps/public/embeddable/synchronize_movement.ts +++ b/x-pack/plugins/maps/public/embeddable/map_embeddables_singleton.ts @@ -5,6 +5,7 @@ * 2.0. */ +import _ from 'lodash'; import { MapCenterAndZoom } from '../../common/descriptor_types'; interface MapPanel { @@ -12,6 +13,9 @@ interface MapPanel { onLocationChange(lat: number, lon: number, zoom: number): void; getIsMovementSynchronized(): boolean; setIsMovementSynchronized(IsMovementSynchronized: boolean): void; + getIsFilterByMapExtent(): boolean; + setIsFilterByMapExtent(isFilterByMapExtent: boolean): void; + getGeoFieldNames(): string[]; } const registry: Record = {}; @@ -19,7 +23,14 @@ let location: MapCenterAndZoom | undefined; let primaryPanelId: string | undefined; let primaryPanelTimeoutId: ReturnType | undefined; -export const synchronizeMovement = { +export const mapEmbeddablesSingleton = { + getGeoFieldNames() { + const geoFieldNames: string[] = []; + Object.values(registry).forEach((mapPanel) => { + geoFieldNames.push(...mapPanel.getGeoFieldNames()); + }); + return _.uniq(geoFieldNames); + }, getLocation() { return location; }, diff --git a/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_action.ts b/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_action.ts deleted file mode 100644 index a399c954b367e..0000000000000 --- a/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_action.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; -import { Embeddable, EmbeddableInput, ViewMode } from '@kbn/embeddable-plugin/public'; -import { createAction } from '@kbn/ui-actions-plugin/public'; -import { MAP_SAVED_OBJECT_TYPE } from '../../common/constants'; - -export const FILTER_BY_MAP_EXTENT = 'FILTER_BY_MAP_EXTENT'; - -interface FilterByMapExtentInput extends EmbeddableInput { - filterByMapExtent: boolean; -} - -interface FilterByMapExtentActionContext { - embeddable: Embeddable; -} - -export function getFilterByMapExtent(input: { filterByMapExtent?: boolean }) { - return input.filterByMapExtent === undefined ? false : input.filterByMapExtent; -} - -export const filterByMapExtentAction = createAction({ - id: FILTER_BY_MAP_EXTENT, - type: FILTER_BY_MAP_EXTENT, - order: 20, - getDisplayName: ({ embeddable }: FilterByMapExtentActionContext) => { - return getFilterByMapExtent(embeddable.getInput()) - ? i18n.translate('xpack.maps.filterByMapExtentMenuItem.disableDisplayName', { - defaultMessage: 'Disable filter by map extent', - }) - : i18n.translate('xpack.maps.filterByMapExtentMenuItem.enableDisplayName', { - defaultMessage: 'Enable filter by map extent', - }); - }, - getIconType: () => { - return 'filter'; - }, - isCompatible: async ({ embeddable }: FilterByMapExtentActionContext) => { - return ( - embeddable.type === MAP_SAVED_OBJECT_TYPE && - embeddable.getInput().viewMode === ViewMode.EDIT && - !embeddable.getInput().disableTriggers - ); - }, - execute: async ({ embeddable }: FilterByMapExtentActionContext) => { - embeddable.updateInput({ - filterByMapExtent: !getFilterByMapExtent(embeddable.getInput()), - }); - }, -}); diff --git a/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_action.tsx b/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_action.tsx new file mode 100644 index 0000000000000..b9d70bf4afbf3 --- /dev/null +++ b/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_action.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { Embeddable, EmbeddableInput } from '@kbn/embeddable-plugin/public'; +import { createReactOverlays } from '@kbn/kibana-react-plugin/public'; +import { createAction } from '@kbn/ui-actions-plugin/public'; +import { MAP_SAVED_OBJECT_TYPE } from '../../common/constants'; +import { getCore } from '../kibana_services'; + +export const FILTER_BY_MAP_EXTENT = 'FILTER_BY_MAP_EXTENT'; + +interface FilterByMapExtentInput extends EmbeddableInput { + filterByMapExtent: boolean; +} + +interface FilterByMapExtentActionContext { + embeddable: Embeddable; +} + +function getContainerLabel(embeddable: Embeddable) { + return embeddable.parent?.type === 'dashboard' + ? i18n.translate('xpack.maps.filterByMapExtentMenuItem.dashboardLabel', { + defaultMessage: 'dashboard', + }) + : i18n.translate('xpack.maps.filterByMapExtentMenuItem.pageLabel', { + defaultMessage: 'page', + }); +} + +function getDisplayName(embeddable: Embeddable) { + return i18n.translate('xpack.maps.filterByMapExtentMenuItem.displayName', { + defaultMessage: 'Filter {containerLabel} by map bounds', + values: { containerLabel: getContainerLabel(embeddable) }, + }); +} + +export const filterByMapExtentAction = createAction({ + id: FILTER_BY_MAP_EXTENT, + type: FILTER_BY_MAP_EXTENT, + order: 20, + getDisplayName: (context: FilterByMapExtentActionContext) => { + return getDisplayName(context.embeddable); + }, + getDisplayNameTooltip: (context: FilterByMapExtentActionContext) => { + return i18n.translate('xpack.maps.filterByMapExtentMenuItem.displayNameTooltip', { + defaultMessage: + 'As you zoom and pan the map, the {containerLabel} updates to display only the data visible in the map bounds.', + values: { containerLabel: getContainerLabel(context.embeddable) }, + }); + }, + getIconType: () => { + return 'filter'; + }, + isCompatible: async ({ embeddable }: FilterByMapExtentActionContext) => { + return embeddable.type === MAP_SAVED_OBJECT_TYPE && !embeddable.getInput().disableTriggers; + }, + execute: async (context: FilterByMapExtentActionContext) => { + const { FilterByMapExtentModal } = await import('./filter_by_map_extent_modal'); + const { openModal } = createReactOverlays(getCore()); + const modalSession = openModal( + modalSession.close()} + title={getDisplayName(context.embeddable)} + /> + ); + }, +}); diff --git a/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_modal.tsx b/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_modal.tsx new file mode 100644 index 0000000000000..206f754ae65bb --- /dev/null +++ b/x-pack/plugins/maps/public/trigger_actions/filter_by_map_extent_modal.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { Component, Fragment } from 'react'; +import { + EuiFormRow, + EuiModalHeader, + EuiModalBody, + EuiModalHeaderTitle, + EuiSwitch, + EuiSwitchEvent, +} from '@elastic/eui'; +import { mapEmbeddablesSingleton } from '../embeddable/map_embeddables_singleton'; + +interface Props { + onClose: () => void; + title: string; +} + +export class FilterByMapExtentModal extends Component { + _renderSwitches() { + return mapEmbeddablesSingleton.getMapPanels().map((mapPanel) => { + return ( + + { + const isChecked = event.target.checked; + mapPanel.setIsFilterByMapExtent(isChecked); + + // only a single map can create map bound filter at a time + // disable all other map panels from creating map bound filter + if (isChecked) { + mapEmbeddablesSingleton.getMapPanels().forEach((it) => { + if (it.id !== mapPanel.id && it.getIsFilterByMapExtent()) { + it.setIsFilterByMapExtent(false); + } + }); + } + this.forceUpdate(); + }} + compressed + data-test-subj={`filterByMapExtentSwitch${mapPanel.id}`} + /> + + ); + }); + } + + render() { + return ( + + + {this.props.title} + + + {this._renderSwitches()} + + ); + } +} diff --git a/x-pack/plugins/maps/public/trigger_actions/synchronize_movement_action.tsx b/x-pack/plugins/maps/public/trigger_actions/synchronize_movement_action.tsx index aa6ff6c33c18f..e3404c628a54f 100644 --- a/x-pack/plugins/maps/public/trigger_actions/synchronize_movement_action.tsx +++ b/x-pack/plugins/maps/public/trigger_actions/synchronize_movement_action.tsx @@ -39,8 +39,8 @@ export const synchronizeMovementAction = createAction { - const { synchronizeMovement } = await import('../embeddable/synchronize_movement'); - if (!synchronizeMovement.hasMultipleMaps()) { + const { mapEmbeddablesSingleton } = await import('../embeddable/map_embeddables_singleton'); + if (!mapEmbeddablesSingleton.hasMultipleMaps()) { return false; } diff --git a/x-pack/plugins/maps/public/trigger_actions/synchronize_movement_modal.tsx b/x-pack/plugins/maps/public/trigger_actions/synchronize_movement_modal.tsx index dee5aae53f442..c6a1dae7eb36b 100644 --- a/x-pack/plugins/maps/public/trigger_actions/synchronize_movement_modal.tsx +++ b/x-pack/plugins/maps/public/trigger_actions/synchronize_movement_modal.tsx @@ -15,7 +15,7 @@ import { EuiSwitch, EuiSwitchEvent, } from '@elastic/eui'; -import { synchronizeMovement } from '../embeddable/synchronize_movement'; +import { mapEmbeddablesSingleton } from '../embeddable/map_embeddables_singleton'; interface Props { onClose: () => void; @@ -23,7 +23,7 @@ interface Props { export class SynchronizeMovementModal extends Component { _renderSwitches() { - const mapPanels = synchronizeMovement.getMapPanels(); + const mapPanels = mapEmbeddablesSingleton.getMapPanels(); const synchronizedPanels = mapPanels.filter((mapPanel) => { return mapPanel.getIsMovementSynchronized(); diff --git a/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx b/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx index 43bc5e77dbb82..cb6e7061fa319 100644 --- a/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx +++ b/x-pack/plugins/ml/public/application/aiops/explain_log_rate_spikes.tsx @@ -5,18 +5,14 @@ * 2.0. */ -import React, { useEffect, useState, FC } from 'react'; +import React, { FC } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { ExplainLogRateSpikes } from '@kbn/aiops-plugin/public'; -import { getWindowParameters } from '@kbn/aiops-utils'; -import type { WindowParameters } from '@kbn/aiops-utils'; -import { KBN_FIELD_TYPES } from '@kbn/data-plugin/public'; import { useMlContext } from '../contexts/ml'; import { useMlKibana } from '../contexts/kibana'; import { HelpMenu } from '../components/help_menu'; -import { ml } from '../services/ml_api_service'; import { MlPageHeader } from '../components/page_header'; @@ -28,36 +24,6 @@ export const ExplainLogRateSpikesPage: FC = () => { const context = useMlContext(); const dataView = context.currentDataView; - const [windowParameters, setWindowParameters] = useState(); - - useEffect(() => { - async function fetchWindowParameters() { - if (dataView.timeFieldName) { - const stats: Array<{ - data: Array<{ doc_count: number; key: number }>; - stats: [number, number]; - }> = await ml.getVisualizerFieldHistograms({ - indexPattern: dataView.title, - fields: [{ fieldName: dataView.timeFieldName, type: KBN_FIELD_TYPES.DATE }], - query: { match_all: {} }, - samplerShardSize: -1, - }); - - const peak = stats[0].data.reduce((p, c) => (c.doc_count >= p.doc_count ? c : p), { - doc_count: 0, - key: 0, - }); - const peakTimestamp = Math.round(peak.key); - - setWindowParameters( - getWindowParameters(peakTimestamp, stats[0].stats[0], stats[0].stats[1]) - ); - } - } - - fetchWindowParameters(); - }, []); - return ( <> @@ -66,9 +32,7 @@ export const ExplainLogRateSpikesPage: FC = () => { defaultMessage="Explain log rate spikes" /> - {dataView.timeFieldName && windowParameters && ( - - )} + {dataView.timeFieldName && } ); diff --git a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js index bbf5dc81768a1..a0a364e3af0f8 100644 --- a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js +++ b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js @@ -51,6 +51,7 @@ import { ML_APP_LOCATOR, ML_PAGES } from '../../../../../common/constants/locato import { timeFormatter } from '../../../../../common/util/date_utils'; import { MlAnnotationUpdatesContext } from '../../../contexts/ml/ml_annotation_updates_context'; import { DatafeedChartFlyout } from '../../../jobs/jobs_list/components/datafeed_chart_flyout'; +import { RevertModelSnapshotFlyout } from '../../model_snapshots/revert_model_snapshot_flyout'; const editAnnotationsText = ( ); @@ -72,9 +73,14 @@ const CURRENT_SERIES = 'current_series'; class AnnotationsTableUI extends Component { static propTypes = { annotations: PropTypes.array, + annotationUpdatesService: PropTypes.object.isRequired, jobs: PropTypes.array, + detectors: PropTypes.array, isSingleMetricViewerLinkVisible: PropTypes.bool, isNumberBadgeVisible: PropTypes.bool, + refreshJobList: PropTypes.func, + chartDetails: PropTypes.object, + kibana: PropTypes.object, }; constructor(props) { @@ -91,6 +97,8 @@ class AnnotationsTableUI extends Component { ? this.props.jobs[0].job_id : undefined, datafeedFlyoutVisible: false, + modelSnapshot: null, + revertSnapshotFlyoutVisible: false, datafeedEnd: null, }; this.sorting = { @@ -727,10 +735,30 @@ class AnnotationsTableUI extends Component { datafeedFlyoutVisible: false, }); }} + onModelSnapshotAnnotationClick={(modelSnapshot) => { + this.setState({ + modelSnapshot, + revertSnapshotFlyoutVisible: true, + datafeedFlyoutVisible: false, + }); + }} end={this.state.datafeedEnd} jobId={this.state.jobId} /> ) : null} + {this.state.revertSnapshotFlyoutVisible === true && this.state.modelSnapshot !== null ? ( + { + this.setState({ + revertSnapshotFlyoutVisible: false, + }); + }} + refresh={this.props.refreshJobList ?? (() => {})} + /> + ) : null} ); } diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_chart_flyout/datafeed_chart_flyout.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_chart_flyout/datafeed_chart_flyout.tsx index cce322156af3a..8c4b96207b3a5 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_chart_flyout/datafeed_chart_flyout.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_chart_flyout/datafeed_chart_flyout.tsx @@ -50,12 +50,14 @@ import { DATAFEED_STATE } from '../../../../../../common/constants/states'; import { CombinedJobWithStats, ModelSnapshot, + MlSummaryJob, } from '../../../../../../common/types/anomaly_detection_jobs'; import { JobMessage } from '../../../../../../common/types/audit_message'; import { LineAnnotationDatumWithModelSnapshot } from '../../../../../../common/types/results'; import { useToastNotificationService } from '../../../../services/toast_notification_service'; import { useMlApiContext } from '../../../../contexts/kibana'; import { useCurrentEuiTheme } from '../../../../components/color_range_legend'; +import { RevertModelSnapshotFlyout } from '../../../../components/model_snapshots/revert_model_snapshot_flyout'; import { JobMessagesPane } from '../job_details/job_messages_pane'; import { EditQueryDelay } from './edit_query_delay'; import { CHART_DIRECTION, ChartDirectionType, CHART_SIZE } from './constants'; @@ -595,3 +597,87 @@ export const DatafeedChartFlyout: FC = ({ ); }; + +type ShowFunc = (jobUpdate: MlSummaryJob) => void; + +interface JobListDatafeedChartFlyoutProps { + setShowFunction: (showFunc: ShowFunc) => void; + unsetShowFunction: () => void; + refreshJobs(): void; +} + +/** + * Component to wire the datafeed chart flyout with the Job list view. + * @param setShowFunction function to show the flyout + * @param unsetShowFunction function called when flyout is closed + * @param refreshJobs function to refresh the jobs list + * @constructor + */ +export const JobListDatafeedChartFlyout: FC = ({ + setShowFunction, + unsetShowFunction, + refreshJobs, +}) => { + const [isVisible, setIsVisible] = useState(false); + const [job, setJob] = useState(); + const [jobWithStats, setJobWithStats] = useState(); + + const [isRevertModelSnapshotFlyoutVisible, setIsRevertModelSnapshotFlyoutVisible] = + useState(false); + const [snapshot, setSnapshot] = useState(null); + + const showFlyoutCallback = useCallback((jobUpdate: MlSummaryJob) => { + setJob(jobUpdate); + setIsVisible(true); + }, []); + + const showRevertModelSnapshot = useCallback(async () => { + // Need to load the full job with stats, as the model snapshot + // flyout needs the timestamp of the last result. + const fullJob: CombinedJobWithStats = await loadFullJob(job!.id); + setJobWithStats(fullJob); + setIsRevertModelSnapshotFlyoutVisible(true); + }, [job]); + + useEffect(() => { + setShowFunction(showFlyoutCallback); + return () => { + unsetShowFunction(); + }; + }, []); + + if (isVisible === true && job !== undefined) { + return ( + setIsVisible(false)} + onModelSnapshotAnnotationClick={(modelSnapshot) => { + setIsVisible(false); + setSnapshot(modelSnapshot); + showRevertModelSnapshot(); + }} + end={job.latestResultsTimestampMs || Date.now()} + jobId={job.id} + /> + ); + } + + if ( + isRevertModelSnapshotFlyoutVisible === true && + jobWithStats !== undefined && + snapshot !== null + ) { + return ( + { + setIsRevertModelSnapshotFlyoutVisible(false); + }} + refresh={refreshJobs} + /> + ); + } + + return null; +}; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_chart_flyout/index.ts b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_chart_flyout/index.ts index ba1b6ae0b9707..1606c9491dee9 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_chart_flyout/index.ts +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/datafeed_chart_flyout/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { DatafeedChartFlyout } from './datafeed_chart_flyout'; +export { DatafeedChartFlyout, JobListDatafeedChartFlyout } from './datafeed_chart_flyout'; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_actions/management.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_actions/management.js index 5b8b4b386213d..29045ad826bdf 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_actions/management.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_actions/management.js @@ -23,6 +23,7 @@ import { isManagedJob } from '../../../jobs_utils'; export function actionsMenuContent( showEditJobFlyout, + showDatafeedChartFlyout, showDeleteJobModal, showResetJobModal, showStartDatafeedModal, @@ -34,6 +35,7 @@ export function actionsMenuContent( const canCreateJob = checkPermission('canCreateJob') && mlNodesAvailable(); const canUpdateJob = checkPermission('canUpdateJob'); const canDeleteJob = checkPermission('canDeleteJob'); + const canGetDatafeeds = checkPermission('canGetDatafeeds'); const canUpdateDatafeed = checkPermission('canUpdateDatafeed'); const canStartStopDatafeed = checkPermission('canStartStopDatafeed') && mlNodesAvailable(); const canCloseJob = checkPermission('canCloseJob') && mlNodesAvailable(); @@ -152,6 +154,25 @@ export function actionsMenuContent( }, 'data-test-subj': 'mlActionButtonCloneJob', }, + { + name: i18n.translate('xpack.ml.jobsList.managementActions.viewDatafeedCountsLabel', { + defaultMessage: 'View datafeed counts', + }), + description: i18n.translate( + 'xpack.ml.jobsList.managementActions.viewDatafeedCountsDescription', + { + defaultMessage: 'View datafeed counts', + } + ), + icon: 'visAreaStacked', + enabled: () => canGetDatafeeds, + available: () => canGetDatafeeds, + onClick: (item) => { + showDatafeedChartFlyout(item); + closeMenu(); + }, + 'data-test-subj': 'mlActionButtonViewDatafeedChart', + }, { name: i18n.translate('xpack.ml.jobsList.managementActions.editJobLabel', { defaultMessage: 'Edit job', diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details.js index 5a62800a6ce39..8d98052eab26c 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details.js @@ -9,7 +9,7 @@ import PropTypes from 'prop-types'; import React, { Component, Fragment } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { EuiButtonIcon, EuiTabbedContent, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; +import { EuiButtonEmpty, EuiTabbedContent, EuiLoadingSpinner } from '@elastic/eui'; import { extractJobDetails } from './extract_job_details'; import { JsonPane } from './json_tab'; @@ -84,27 +84,20 @@ export class JobDetailsUI extends Component { } = extractJobDetails(job, basePath, refreshJobList); datafeed.titleAction = ( - + + this.setState({ + datafeedChartFlyoutVisible: true, + }) } + iconType="visAreaStacked" + size="s" > - - this.setState({ - datafeedChartFlyoutVisible: true, - }) - } + - + ); const tabs = [ @@ -248,7 +241,7 @@ export class JobDetailsUI extends Component { }), content: ( - + ), diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.js index 4046f4d5d8071..c70c049dd7489 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.js @@ -44,7 +44,7 @@ function Section({ section }) { return ( - +

    {section.title}

    diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js index a475f39a8c10b..09a783dd5ad7f 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js @@ -330,6 +330,7 @@ export class JobsList extends Component { ), actions: actionsMenuContent( this.props.showEditJobFlyout, + this.props.showDatafeedChartFlyout, this.props.showDeleteJobModal, this.props.showResetJobModal, this.props.showStartDatafeedModal, @@ -406,6 +407,7 @@ JobsList.propTypes = { toggleRow: PropTypes.func.isRequired, selectJobChange: PropTypes.func.isRequired, showEditJobFlyout: PropTypes.func, + showDatafeedChartFlyout: PropTypes.func, showDeleteJobModal: PropTypes.func, showStartDatafeedModal: PropTypes.func, showCloseJobsConfirmModal: PropTypes.func, diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js index 5e65a9bec23d6..0eb7f810932fb 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js @@ -14,6 +14,7 @@ import { JobsList } from '../jobs_list'; import { JobDetails } from '../job_details'; import { JobFilterBar } from '../job_filter_bar'; import { EditJobFlyout } from '../edit_job_flyout'; +import { JobListDatafeedChartFlyout } from '../datafeed_chart_flyout'; import { DeleteJobModal } from '../delete_job_modal'; import { ResetJobModal } from '../reset_job_modal'; import { StartDatafeedModal } from '../start_datafeed_modal'; @@ -53,6 +54,7 @@ export class JobsListView extends Component { this.updateFunctions = {}; this.showEditJobFlyout = () => {}; + this.showDatafeedChartFlyout = () => {}; this.showStopDatafeedsConfirmModal = () => {}; this.showCloseJobsConfirmModal = () => {}; this.showDeleteJobModal = () => {}; @@ -178,6 +180,13 @@ export class JobsListView extends Component { this.showEditJobFlyout = () => {}; }; + setShowDatafeedChartFlyoutFunction = (func) => { + this.showDatafeedChartFlyout = func; + }; + unsetShowDatafeedChartFlyoutFunction = () => { + this.showDatafeedChartFlyout = () => {}; + }; + setShowStopDatafeedsConfirmModalFunction = (func) => { this.showStopDatafeedsConfirmModal = func; }; @@ -437,6 +446,7 @@ export class JobsListView extends Component { toggleRow={this.toggleRow} selectJobChange={this.selectJobChange} showEditJobFlyout={this.showEditJobFlyout} + showDatafeedChartFlyout={this.showDatafeedChartFlyout} showDeleteJobModal={this.showDeleteJobModal} showResetJobModal={this.showResetJobModal} showCloseJobsConfirmModal={this.showCloseJobsConfirmModal} @@ -459,13 +469,17 @@ export class JobsListView extends Component { refreshJobs={() => this.refreshJobSummaryList(true)} allJobIds={jobIds} /> + this.refreshJobSummaryList(true)} + /> this.refreshJobSummaryList(true)} allJobIds={jobIds} /> - diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/_time_range_selector.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/_time_range_selector.scss index 65a72a1d4a48d..faa69e90ecab5 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/_time_range_selector.scss +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/_time_range_selector.scss @@ -1,9 +1,6 @@ // stylelint-disable selector-no-qualifying-type // SASSTODO: Looks like this could use a rewrite. Needs selectors .time-range-selector { - .time-range-section-container { - display: flex; - } .time-range-section-title { font-weight: bold; margin-bottom: $euiSizeS; @@ -46,7 +43,6 @@ } .body { display: block; - height: 315px; } } & > li.has-body.active { diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js index 4300a918b948f..05e8e60abc4fb 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/start_datafeed_modal/time_range_selector/time_range_selector.js @@ -9,7 +9,7 @@ import './_time_range_selector.scss'; import PropTypes from 'prop-types'; import React, { Component, useState, useEffect } from 'react'; -import { EuiDatePicker, EuiFieldText, EuiSpacer } from '@elastic/eui'; +import { EuiDatePicker, EuiFieldText, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import moment from 'moment'; import { i18n } from '@kbn/i18n'; @@ -181,30 +181,34 @@ export class TimeRangeSelector extends Component { ) : null} -
    - - } - items={startItems} - switchState={this.state.startTab} - switchFunc={this.setStartTab} - /> - - } - items={endItems} - switchState={this.state.endTab} - switchFunc={this.setEndTab} - /> -
    + + + + } + items={startItems} + switchState={this.state.startTab} + switchFunc={this.setStartTab} + /> + + + + } + items={endItems} + switchState={this.state.endTab} + switchFunc={this.setEndTab} + /> + +
    ); } diff --git a/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx b/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx index c8143a5c283e4..0c8f1aec7d97d 100644 --- a/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx @@ -94,7 +94,7 @@ export const ModelsList: FC = ({ } = useMlKibana(); const urlLocator = useMlLocator()!; - const startModelDeploymentDocUrl = docLinks.links.ml.startTrainedModelsDeploymentQueryParams; + const startModelDeploymentDocUrl = docLinks.links.ml.startTrainedModelsDeployment; useTimefilter({ timeRangeSelector: false, autoRefreshSelector: true }); diff --git a/x-pack/plugins/monitoring_collection/README.md b/x-pack/plugins/monitoring_collection/README.md index 1f2d2984af886..1f9cadf40ee7b 100644 --- a/x-pack/plugins/monitoring_collection/README.md +++ b/x-pack/plugins/monitoring_collection/README.md @@ -2,4 +2,139 @@ ## Plugin -This plugin allows for other plugins to add data to Kibana stack monitoring documents. \ No newline at end of file +This plugin allows for other plugins to add data to Kibana stack monitoring documents. + +## OpenTelemetry Metrics + +### Enable Prometheus endpoint with Elastic Agent Prometheus input + +1. Start [local setup with fleet](../fleet/README.md#running-fleet-server-locally-in-a-container) or a cloud cluster +2. Start Kibana +3. Set up a new agent policy and enroll a new agent in your local machine +4. Install the Prometheus Metrics package + 1. Set **Hosts** with `localhost:5601` + 2. Set **Metrics Path** with `/(BASEPATH)/api/monitoring_collection/v1/prometheus` + 3. Remove the values from **Bearer Token File** and **SSL Certificate Authorities** + 4. Set **Username** and **Password** with `elastic` and `changeme` +5. Add the following configuration to `kibana.dev.yml` + + ```yml + # Enable the prometheus exporter + monitoring_collection.opentelemetry.metrics: + prometheus.enabled: true + ``` + +### Enable OpenTelemetry Metrics API exported as OpenTelemetry Protocol over GRPC + +1. Start [local setup with fleet](../fleet/README.md#running-fleet-server-locally-in-a-container) or a cloud cluster +2. Start Kibana +3. Set up a new agent policy and enroll a new agent in your local machine +4. Install Elastic APM package listening on `localhost:8200` without authentication +5. Add the following configuration to `kibana.dev.yml` + + ```yml + # Enable the OTLP exporter + monitoring_collection.opentelemetry.metrics: + otlp.url: "http://127.0.0.1:8200" + ``` + +You can also provide headers for OTLP endpoints that require authentication: + +```yml +# Enable the OTLP exporter to an authenticated APM endpoint +monitoring_collection.opentelemetry.metrics: + otlp: + url: "https://DEPLOYMENT.apm.REGION.PROVIDER.elastic-cloud.com" + headers: + Authorization: "Bearer SECRET_TOKEN" +``` + +Alternatively, OTLP Exporter can be configured using environment variables `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` and `OTEL_EXPORTER_OTLP_METRICS_HEADERS`. [See OTLP Exporter docs](https://opentelemetry.io/docs/reference/specification/protocol/exporter/) for details. + +It's possible to configure logging for the OTLP integration. If not informed, the default will be `info` + +```yml +monitoring_collection.opentelemetry.metrics: + logLevel: warn | info | debug | warn | none | verbose | all +``` + +For connection-level debug information you can set these variables: + +```bash +export GRPC_NODE_TRACE="xds_client,xds_resolver,cds_balancer,eds_balancer,priority,weighted_target,round_robin,resolving_load_balancer,subchannel,keepalive,dns_resolver,fault_injection,http_filter,csds" +export GRPC_NODE_VERBOSITY=DEBUG +``` + +See the [grpc-node docs](https://github.com/grpc/grpc-node/blob/master/doc/environment_variables.md) for details and other settings. + +### Example of how to instrument the code + +* First, we need to define what metrics we want to instrument with OpenTelemetry + + ```ts + import { Counter, Meter } from '@opentelemetry/api-metrics'; + + export class FooApiMeters { + requestCount: Counter; + + constructor(meter: Meter) { + this.requestCount = meter.createCounter('request_count', { + description: 'Counts total number of requests', + }); + } + } + ``` + + In this example we're using a `Counter` metric, but [OpenTelemetry SDK](https://open-telemetry.github.io/opentelemetry-js/interfaces/_opentelemetry_api_metrics.Meter.html) provides there are other options to record metrics + +* Initialize meter in the plugin setup and pass it to the relevant components that will be instrumented. In this case, we want to instrument `FooApi` routes. + + ```ts + import { IRouter } from '@kbn/core/server'; + import { FooApiMeters } from './foo_api_meters'; + import { metrics } from '@opentelemetry/api-metrics'; + + export class FooApiPlugin implements Plugin { + private metrics: Metrics; + private libs: { router: IRouter, metrics: FooApiMeters}; + + constructor() { + this.metrics = new Metrics(metrics.getMeter('kibana.fooApi')); + } + + public setup(core: CoreSetup) { + const router = core.http.createRouter(); + + this.libs = { + router, + metrics: this.metrics + } + + initMetricsAPIRoute(this.libs); + } + } + ``` + + `monitoring_collection` plugins has to be initialized before the plugin that will be instrumented. If for some reason the instrumentation doesn't record any metrics, make sure `monitoring_collection` is included in the list of `requiredPlugins`. e.g: + + ```json + "requiredPlugins": [ + "monitoringCollection" + ], + ``` + +* Lastly we can use the `metrics` object to instrument the code + + ```ts + export const initMetricsAPIRoute = (libs: { router: IRouter, metrics: FooApiMeters}) => { + router.get( + { + path: '/api/foo', + validate: {}, + }, + async function (_context, _req, res) { + metrics.requestCount.add(1); + return res.ok({}); + } + ); + ``` \ No newline at end of file diff --git a/x-pack/plugins/monitoring_collection/server/config.ts b/x-pack/plugins/monitoring_collection/server/config.ts index 275d2f31e505d..5eda950ebe7f1 100644 --- a/x-pack/plugins/monitoring_collection/server/config.ts +++ b/x-pack/plugins/monitoring_collection/server/config.ts @@ -9,6 +9,19 @@ import { schema, TypeOf } from '@kbn/config-schema'; export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), + opentelemetry: schema.object({ + metrics: schema.object({ + otlp: schema.object({ + url: schema.maybe(schema.string()), + headers: schema.maybe(schema.recordOf(schema.string(), schema.string())), + exportIntervalMillis: schema.number({ defaultValue: 10000 }), + logLevel: schema.string({ defaultValue: 'info' }), + }), + prometheus: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + }), + }), + }), }); export type MonitoringCollectionConfig = ReturnType; diff --git a/x-pack/plugins/monitoring_collection/server/constants.ts b/x-pack/plugins/monitoring_collection/server/constants.ts index 86231dec6c6c2..92b43a9d80e48 100644 --- a/x-pack/plugins/monitoring_collection/server/constants.ts +++ b/x-pack/plugins/monitoring_collection/server/constants.ts @@ -5,3 +5,5 @@ * 2.0. */ export const TYPE_ALLOWLIST = ['node_rules', 'cluster_rules', 'node_actions', 'cluster_actions']; + +export const MONITORING_COLLECTION_BASE_PATH = '/api/monitoring_collection'; diff --git a/x-pack/plugins/monitoring_collection/server/lib/index.ts b/x-pack/plugins/monitoring_collection/server/lib/index.ts index 0c39a62ab359c..34c1fce763bdc 100644 --- a/x-pack/plugins/monitoring_collection/server/lib/index.ts +++ b/x-pack/plugins/monitoring_collection/server/lib/index.ts @@ -7,3 +7,4 @@ export { getKibanaStats } from './get_kibana_stats'; export { getESClusterUuid } from './get_es_cluster_uuid'; +export { PrometheusExporter } from './prometheus_exporter'; diff --git a/x-pack/plugins/monitoring_collection/server/lib/prometheus_exporter.ts b/x-pack/plugins/monitoring_collection/server/lib/prometheus_exporter.ts new file mode 100644 index 0000000000000..fc4359609bf34 --- /dev/null +++ b/x-pack/plugins/monitoring_collection/server/lib/prometheus_exporter.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AggregationTemporality, MetricReader } from '@opentelemetry/sdk-metrics-base'; +import { + PrometheusExporter as OpenTelemetryPrometheusExporter, + ExporterConfig, + PrometheusSerializer, +} from '@opentelemetry/exporter-prometheus'; +import { KibanaResponseFactory } from '@kbn/core/server'; + +export class PrometheusExporter extends MetricReader { + private readonly prefix?: string; + private readonly appendTimestamp: boolean; + private serializer: PrometheusSerializer; + + constructor(config: ExporterConfig = {}) { + super(); + this.prefix = config.prefix || OpenTelemetryPrometheusExporter.DEFAULT_OPTIONS.prefix; + this.appendTimestamp = + typeof config.appendTimestamp === 'boolean' + ? config.appendTimestamp + : OpenTelemetryPrometheusExporter.DEFAULT_OPTIONS.appendTimestamp; + + this.serializer = new PrometheusSerializer(this.prefix, this.appendTimestamp); + } + + selectAggregationTemporality(): AggregationTemporality { + return AggregationTemporality.CUMULATIVE; + } + + protected onForceFlush(): Promise { + return Promise.resolve(undefined); + } + + protected onShutdown(): Promise { + return Promise.resolve(undefined); + } + + /** + * Responds to incoming message with current state of all metrics. + */ + public async exportMetrics(res: KibanaResponseFactory) { + try { + const collectionResult = await this.collect(); + const { resourceMetrics, errors } = collectionResult; + if (errors.length) { + return res.customError({ + statusCode: 500, + body: `PrometheusExporter: Metrics collection errors ${errors}`, + }); + } + const result = this.serializer.serialize(resourceMetrics); + if (result === '') { + return res.noContent(); + } + return res.ok({ + body: result, + }); + } catch (error) { + return res.customError({ + statusCode: 500, + body: { + message: `PrometheusExporter: Failed to export metrics ${error}`, + }, + }); + } + } +} diff --git a/x-pack/plugins/monitoring_collection/server/plugin.ts b/x-pack/plugins/monitoring_collection/server/plugin.ts index e1c3a5064a579..1c30a8439cf3c 100644 --- a/x-pack/plugins/monitoring_collection/server/plugin.ts +++ b/x-pack/plugins/monitoring_collection/server/plugin.ts @@ -6,10 +6,24 @@ */ import { JsonObject } from '@kbn/utility-types'; -import { CoreSetup, Plugin, PluginInitializerContext, Logger } from '@kbn/core/server'; +import { + CoreSetup, + Plugin, + PluginInitializerContext, + Logger, + ServiceStatus, +} from '@kbn/core/server'; import { MakeSchemaFrom } from '@kbn/usage-collection-plugin/server'; -import { ServiceStatus } from '@kbn/core/server'; -import { registerDynamicRoute } from './routes'; +import { metrics } from '@opentelemetry/api-metrics'; +import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc'; +import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics-base'; +import { Resource } from '@opentelemetry/resources'; +import { diag, DiagLogger, DiagLogLevel } from '@opentelemetry/api'; +import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'; +import * as grpc from '@grpc/grpc-js'; +import { PrometheusExporter } from './lib/prometheus_exporter'; +import { MonitoringCollectionConfig } from './config'; +import { registerDynamicRoute, registerV1PrometheusRoute, PROMETHEUS_PATH } from './routes'; import { TYPE_ALLOWLIST } from './constants'; export interface MonitoringCollectionSetup { @@ -27,12 +41,25 @@ export interface Metric { export class MonitoringCollectionPlugin implements Plugin { private readonly initializerContext: PluginInitializerContext; private readonly logger: Logger; + private readonly config: MonitoringCollectionConfig; + private readonly otlpLogger: DiagLogger; private metrics: Record> = {}; - constructor(initializerContext: PluginInitializerContext) { + private prometheusExporter?: PrometheusExporter; + + constructor(initializerContext: PluginInitializerContext) { this.initializerContext = initializerContext; this.logger = initializerContext.logger.get(); + this.config = initializerContext.config.get(); + + this.otlpLogger = { + debug: (message) => this.logger.debug(message), + error: (message) => this.logger.error(message), + info: (message) => this.logger.info(message), + warn: (message) => this.logger.warn(message), + verbose: (message) => this.logger.trace(message), + }; } async getMetric(type: string) { @@ -46,19 +73,28 @@ export class MonitoringCollectionPlugin implements Plugin; core.status.overall$.subscribe((newStatus) => { status = newStatus; }); + if (this.prometheusExporter) { + registerV1PrometheusRoute({ router, prometheusExporter: this.prometheusExporter }); + } + registerDynamicRoute({ router, config: { kibanaIndex, - kibanaVersion: this.initializerContext.env.packageInfo.version, - server: core.http.getServerInfo(), - uuid: this.initializerContext.env.instanceUuid, + kibanaVersion, + server, + uuid, }, getStatus: () => status, getMetric: async (type: string) => { @@ -85,6 +121,58 @@ export class MonitoringCollectionPlugin implements Plugin { jest.resetAllMocks(); }); -jest.mock('../lib', () => ({ +jest.mock('../../../../lib', () => ({ getESClusterUuid: () => 'clusterA', getKibanaStats: () => ({ name: 'myKibana' }), })); diff --git a/x-pack/plugins/monitoring_collection/server/routes/dynamic_route.ts b/x-pack/plugins/monitoring_collection/server/routes/api/v1/dynamic_route/get_metrics_by_type.ts similarity index 86% rename from x-pack/plugins/monitoring_collection/server/routes/dynamic_route.ts rename to x-pack/plugins/monitoring_collection/server/routes/api/v1/dynamic_route/get_metrics_by_type.ts index 944037dd17a7b..4d18eeb6ec922 100644 --- a/x-pack/plugins/monitoring_collection/server/routes/dynamic_route.ts +++ b/x-pack/plugins/monitoring_collection/server/routes/api/v1/dynamic_route/get_metrics_by_type.ts @@ -7,8 +7,9 @@ import { JsonObject } from '@kbn/utility-types'; import { schema } from '@kbn/config-schema'; import { IRouter, ServiceStatus } from '@kbn/core/server'; -import { getESClusterUuid, getKibanaStats } from '../lib'; -import { MetricResult } from '../plugin'; +import { getESClusterUuid, getKibanaStats } from '../../../../lib'; +import { MetricResult } from '../../../../plugin'; +import { MONITORING_COLLECTION_BASE_PATH } from '../../../../constants'; export function registerDynamicRoute({ router, @@ -34,7 +35,7 @@ export function registerDynamicRoute({ }) { router.get( { - path: `/api/monitoring_collection/{type}`, + path: `${MONITORING_COLLECTION_BASE_PATH}/{type}`, options: { authRequired: true, tags: ['api'], // ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page diff --git a/x-pack/plugins/monitoring_collection/server/routes/api/v1/dynamic_route/index.ts b/x-pack/plugins/monitoring_collection/server/routes/api/v1/dynamic_route/index.ts new file mode 100644 index 0000000000000..973d525b9a77b --- /dev/null +++ b/x-pack/plugins/monitoring_collection/server/routes/api/v1/dynamic_route/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export * from './get_metrics_by_type'; diff --git a/x-pack/plugins/monitoring_collection/server/routes/api/v1/index.ts b/x-pack/plugins/monitoring_collection/server/routes/api/v1/index.ts new file mode 100644 index 0000000000000..e5a70f3f79abc --- /dev/null +++ b/x-pack/plugins/monitoring_collection/server/routes/api/v1/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export { registerDynamicRoute } from './dynamic_route'; +export { registerV1PrometheusRoute, PROMETHEUS_PATH } from './prometheus'; diff --git a/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/get_metrics.test.ts b/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/get_metrics.test.ts new file mode 100644 index 0000000000000..b136d982992c4 --- /dev/null +++ b/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/get_metrics.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { RequestHandlerContext } from '@kbn/core/server'; +import { httpServerMock, httpServiceMock } from '@kbn/core/server/mocks'; +import { registerV1PrometheusRoute } from '.'; +import { PrometheusExporter } from '../../../../lib'; + +describe('Prometheus route', () => { + it('forwards the request to the prometheus exporter', async () => { + const router = httpServiceMock.createRouter(); + const prometheusExporter = { + exportMetrics: jest.fn(), + } as Partial as PrometheusExporter; + + registerV1PrometheusRoute({ router, prometheusExporter }); + + const [, handler] = router.get.mock.calls[0]; + + const context = {} as jest.Mocked; + const req = httpServerMock.createKibanaRequest(); + const factory = httpServerMock.createResponseFactory(); + + await handler(context, req, factory); + + expect(prometheusExporter.exportMetrics).toHaveBeenCalledWith(factory); + }); +}); diff --git a/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/get_metrics.ts b/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/get_metrics.ts new file mode 100644 index 0000000000000..6977be155a4fb --- /dev/null +++ b/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/get_metrics.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IRouter } from '@kbn/core/server'; +import { MONITORING_COLLECTION_BASE_PATH } from '../../../../constants'; +import { PrometheusExporter } from '../../../../lib'; + +export const PROMETHEUS_PATH = `${MONITORING_COLLECTION_BASE_PATH}/v1/prometheus`; +export function registerV1PrometheusRoute({ + router, + prometheusExporter, +}: { + router: IRouter; + prometheusExporter: PrometheusExporter; +}) { + router.get( + { + path: PROMETHEUS_PATH, + options: { + authRequired: true, + tags: ['api'], // ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page + }, + validate: {}, + }, + async (_context, _req, res) => { + return prometheusExporter.exportMetrics(res); + } + ); +} diff --git a/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/index.ts b/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/index.ts new file mode 100644 index 0000000000000..5b99f51c94511 --- /dev/null +++ b/x-pack/plugins/monitoring_collection/server/routes/api/v1/prometheus/index.ts @@ -0,0 +1,7 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export * from './get_metrics'; diff --git a/x-pack/plugins/monitoring_collection/server/routes/index.ts b/x-pack/plugins/monitoring_collection/server/routes/index.ts index eb96ce19f764e..29cd177990593 100644 --- a/x-pack/plugins/monitoring_collection/server/routes/index.ts +++ b/x-pack/plugins/monitoring_collection/server/routes/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { registerDynamicRoute } from './dynamic_route'; +export { registerV1PrometheusRoute, PROMETHEUS_PATH, registerDynamicRoute } from './api/v1'; diff --git a/x-pack/plugins/observability/public/application/application.test.tsx b/x-pack/plugins/observability/public/application/application.test.tsx index 642652a886275..371be0ceb3a34 100644 --- a/x-pack/plugins/observability/public/application/application.test.tsx +++ b/x-pack/plugins/observability/public/application/application.test.tsx @@ -73,7 +73,6 @@ describe('renderApp', () => { appMountParameters: params, observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(), ObservabilityPageTemplate: KibanaPageTemplate, - kibanaFeatures: [], usageCollection: { components: { ApplicationUsageTrackingProvider: (props) => null, diff --git a/x-pack/plugins/observability/public/application/index.tsx b/x-pack/plugins/observability/public/application/index.tsx index e8be9d1fd09ff..16738c81aa540 100644 --- a/x-pack/plugins/observability/public/application/index.tsx +++ b/x-pack/plugins/observability/public/application/index.tsx @@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import ReactDOM from 'react-dom'; import { Route, Router, Switch } from 'react-router-dom'; -import { KibanaFeature } from '@kbn/features-plugin/common'; import { AppMountParameters, APP_WRAPPER_CLASS, CoreStart } from '@kbn/core/public'; import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { @@ -52,7 +51,6 @@ export const renderApp = ({ appMountParameters, observabilityRuleTypeRegistry, ObservabilityPageTemplate, - kibanaFeatures, usageCollection, isDev, }: { @@ -61,7 +59,6 @@ export const renderApp = ({ observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry; appMountParameters: AppMountParameters; ObservabilityPageTemplate: React.ComponentType; - kibanaFeatures: KibanaFeature[]; usageCollection: UsageCollectionSetup; isDev?: boolean; }) => { @@ -92,7 +89,6 @@ export const renderApp = ({ appMountParameters, observabilityRuleTypeRegistry, ObservabilityPageTemplate, - kibanaFeatures, }} > diff --git a/x-pack/plugins/observability/public/assets/onboarding_tour_step_alerts.gif b/x-pack/plugins/observability/public/assets/onboarding_tour_step_alerts.gif new file mode 100644 index 0000000000000..7b81b26ccebbd Binary files /dev/null and b/x-pack/plugins/observability/public/assets/onboarding_tour_step_alerts.gif differ diff --git a/x-pack/plugins/observability/public/assets/onboarding_tour_step_logs.gif b/x-pack/plugins/observability/public/assets/onboarding_tour_step_logs.gif new file mode 100644 index 0000000000000..b3b1668e43067 Binary files /dev/null and b/x-pack/plugins/observability/public/assets/onboarding_tour_step_logs.gif differ diff --git a/x-pack/plugins/observability/public/assets/onboarding_tour_step_metrics.gif b/x-pack/plugins/observability/public/assets/onboarding_tour_step_metrics.gif new file mode 100644 index 0000000000000..9883b732b98c5 Binary files /dev/null and b/x-pack/plugins/observability/public/assets/onboarding_tour_step_metrics.gif differ diff --git a/x-pack/plugins/observability/public/assets/onboarding_tour_step_traces.gif b/x-pack/plugins/observability/public/assets/onboarding_tour_step_traces.gif new file mode 100644 index 0000000000000..7c282e5b4eb24 Binary files /dev/null and b/x-pack/plugins/observability/public/assets/onboarding_tour_step_traces.gif differ diff --git a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx index d3c6b4b2ce0dc..6ba0556fa0172 100644 --- a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx +++ b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx @@ -50,7 +50,6 @@ describe('APMSection', () => { plugins: {} as ObservabilityPublicPluginsStart, observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(), ObservabilityPageTemplate: KibanaPageTemplate, - kibanaFeatures: [], })); }); diff --git a/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx b/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx index 949e83009019e..ee05d2c4b59cb 100644 --- a/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx +++ b/x-pack/plugins/observability/public/components/shared/page_template/page_template.tsx @@ -14,6 +14,7 @@ import type { Observable } from 'rxjs'; import type { ApplicationStart } from '@kbn/core/public'; import { SharedUxServicesProvider } from '@kbn/shared-ux-services'; import type { SharedUXPluginStart } from '@kbn/shared-ux-plugin/public'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; import { KibanaPageTemplate, KibanaPageTemplateProps } from '@kbn/shared-ux-components'; import type { NavigationSection } from '../../../services/navigation_registry'; import { ObservabilityTour } from '../tour'; @@ -64,6 +65,8 @@ export function ObservabilityPageTemplate({ const { pathname: currentPath } = useLocation(); const sharedUXServices = getSharedUXContext(); + const { services } = useKibana(); + const sideNavItems = useMemo>>( () => sections.map(({ label, entries }, sectionIndex) => ({ @@ -130,6 +133,7 @@ export function ObservabilityPageTemplate({ - {i18n.translate('xpack.observability.tour.observabilityOverviewStep.tourContent', { - defaultMessage: - 'Take a quick tour to learn the benefits of having all of your observability data in one stack.', - })} - - ), - anchor: `[id^="SolutionNav"]`, - anchorPosition: 'rightUp', - dataTestSubj: 'overviewStep', - showOverlay: true, - }, - { - title: i18n.translate('xpack.observability.tour.streamStep.tourTitle', { - defaultMessage: 'Tail your infrastructure logs in real time', - }), - content: ( - - {i18n.translate('xpack.observability.tour.streamStep.tourContent', { - defaultMessage: - 'Monitor, filter, and inspect log events flowing in from your applications, servers, virtual machines, and containers.', - })} - - ), - anchor: `[data-nav-id="stream"]`, - anchorPosition: 'rightUp', - dataTestSubj: 'streamStep', - showOverlay: true, - }, - { - title: i18n.translate('xpack.observability.tour.metricsExplorerStep.tourTitle', { - defaultMessage: 'Monitor your infrastructure health', - }), - content: ( - - {i18n.translate('xpack.observability.tour.metricsExplorerStep.tourContent', { - defaultMessage: - 'Stream, group, and visualize metrics from your systems, cloud, network, and other infrastructure sources.', - })} - - ), - anchor: `[data-nav-id="metrics_explorer"]`, - anchorPosition: 'rightUp', - dataTestSubj: 'metricsExplorerStep', - showOverlay: true, - }, - { - title: i18n.translate('xpack.observability.tour.tracesStep.tourTitle', { - defaultMessage: 'Identify and resolve application issues', - }), - content: ( - - {i18n.translate('xpack.observability.tour.tracesStep.tourContent', { - defaultMessage: - 'Find and fix performance problems quickly by collecting detailed information about your services.', - })} - - ), - anchor: `[data-nav-id="traces"]`, - anchorPosition: 'rightUp', - dataTestSubj: 'tracesStep', - showOverlay: true, - }, - { - title: i18n.translate('xpack.observability.tour.alertsStep.tourTitle', { - defaultMessage: 'Get notified when something changes', - }), - content: ( - - {i18n.translate('xpack.observability.tour.alertsStep.tourContent', { - defaultMessage: - 'Define and detect conditions that trigger alerts with third-party platform integrations like email, PagerDuty, and Slack.', - })} - - ), - anchor: `[data-nav-id="alerts"]`, - anchorPosition: 'rightUp', - dataTestSubj: 'alertStep', - showOverlay: true, - }, - { - title: i18n.translate('xpack.observability.tour.guidedSetupStep.tourTitle', { - defaultMessage: 'Now add your data!', - }), - content: ( - - {i18n.translate('xpack.observability.tour.guidedSetupStep.tourContent', { - defaultMessage: - 'The easiest way to get going with Elastic Observability is to follow the Guided setup.', - })} - - ), - anchor: '#guidedSetupButton', - anchorPosition: 'rightUp', - dataTestSubj: 'guidedSetupStep', - showOverlay: false, - }, -]; +export const observTourActiveStorageKey = 'guidedOnboarding.observability.tourActive'; +export const observTourStepStorageKey = 'guidedOnboarding.observability.tourStep'; const getSteps = ({ activeStep, incrementStep, endTour, + prependBasePath, }: { activeStep: number; incrementStep: () => void; endTour: () => void; + prependBasePath?: (imageName: string) => string; }) => { const footerAction = ( @@ -206,7 +94,7 @@ const getSteps = ({ return tourStepsConfig.map((stepConfig, index) => { const step = index + 1; - const { dataTestSubj, showOverlay, ...tourStepProps } = stepConfig; + const { dataTestSubj, content, imageConfig, ...tourStepProps } = stepConfig; return ( + +

    {content}

    +
    + {imageConfig && prependBasePath && ( + <> + + + + )} + + } /> ); }); @@ -233,19 +138,27 @@ interface TourState { isTourActive: boolean; } -const getInitialTourState = (prevTourState: string | null): TourState => { - if (prevTourState) { - try { - const parsedPrevTourState = JSON.parse(prevTourState); - return parsedPrevTourState as TourState; - } catch (e) { - // Fall back to default state - } +const getInitialTourState = ({ + prevIsTourActive, + prevActiveStep, +}: { + prevIsTourActive: string | null; + prevActiveStep: string | null; +}): TourState => { + if (prevIsTourActive === null) { + return { + activeStep: 1, + // Tour is inactive by default + isTourActive: false, + }; } + const isTourActive = prevIsTourActive === 'true'; + const activeStep = prevActiveStep === null ? 1 : Number(prevActiveStep); + return { - activeStep: 1, - isTourActive: false, + activeStep, + isTourActive, }; }; @@ -254,15 +167,21 @@ export function ObservabilityTour({ navigateToApp, isPageDataLoaded, showTour, + prependBasePath, }: { children: ({ isTourVisible }: { isTourVisible: boolean }) => ReactNode; navigateToApp: ApplicationStart['navigateToApp']; isPageDataLoaded: boolean; showTour: boolean; + prependBasePath?: (imageName: string) => string; }) { - const prevTourState = localStorage.getItem(observabilityTourStorageKey); - const { activeStep: initialActiveStep, isTourActive: initialIsTourActive } = - getInitialTourState(prevTourState); + const prevIsTourActive = localStorage.getItem(observTourActiveStorageKey); + const prevActiveStep = localStorage.getItem(observTourStepStorageKey); + + const { activeStep: initialActiveStep, isTourActive: initialIsTourActive } = getInitialTourState({ + prevIsTourActive, + prevActiveStep, + }); const [isTourActive, setIsTourActive] = useState(initialIsTourActive); const [activeStep, setActiveStep] = useState(initialActiveStep); @@ -272,13 +191,16 @@ export function ObservabilityTour({ const isSmallBreakpoint = useIsWithinBreakpoints(['s']); const isOverviewPage = currentPath === overviewPath; - const { showOverlay } = tourStepsConfig[activeStep - 1]; const incrementStep = useCallback(() => { setActiveStep((prevState) => prevState + 1); }, []); - const endTour = useCallback(() => setIsTourActive(false), []); + const endTour = useCallback(() => { + // Reset tour state + setIsTourActive(false); + setActiveStep(1); + }, []); /** * The tour should only be visible if the following conditions are met: @@ -290,8 +212,12 @@ export function ObservabilityTour({ const isTourVisible = showTour && isTourActive && isPageDataLoaded && isSmallBreakpoint === false; useEffect(() => { - localStorage.setItem(observabilityTourStorageKey, JSON.stringify({ isTourActive, activeStep })); - }, [isTourActive, activeStep]); + localStorage.setItem(observTourActiveStorageKey, String(isTourActive)); + }, [isTourActive]); + + useEffect(() => { + localStorage.setItem(observTourStepStorageKey, String(activeStep)); + }, [activeStep]); useEffect(() => { // The user must be on the overview page to view the guided setup step in the tour @@ -305,17 +231,7 @@ export function ObservabilityTour({ return ( <> {children({ isTourVisible })} - {isTourVisible && ( - <> - {getSteps({ activeStep, incrementStep, endTour })} - {showOverlay && ( - - )} - - )} + {isTourVisible && getSteps({ activeStep, incrementStep, endTour, prependBasePath })} ); } diff --git a/x-pack/plugins/observability/public/context/plugin_context.tsx b/x-pack/plugins/observability/public/context/plugin_context.tsx index 91e703d1999fc..b4e6889d957b2 100644 --- a/x-pack/plugins/observability/public/context/plugin_context.tsx +++ b/x-pack/plugins/observability/public/context/plugin_context.tsx @@ -7,7 +7,6 @@ import { AppMountParameters } from '@kbn/core/public'; import { createContext } from 'react'; -import { KibanaFeature } from '@kbn/features-plugin/common'; import { ObservabilityRuleTypeRegistry } from '../rules/create_observability_rule_type_registry'; import type { LazyObservabilityPageTemplateProps } from '../components/shared/page_template/lazy_page_template'; @@ -15,7 +14,6 @@ export interface PluginContextValue { appMountParameters: AppMountParameters; observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry; ObservabilityPageTemplate: React.ComponentType; - kibanaFeatures: KibanaFeature[]; } export const PluginContext = createContext({} as PluginContextValue); diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts b/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts deleted file mode 100644 index b8c3445fffabc..0000000000000 --- a/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useEffect, useState, useCallback } from 'react'; -import { isEmpty } from 'lodash'; -import { loadRules, loadRuleTags } from '@kbn/triggers-actions-ui-plugin/public'; -import { RULES_LOAD_ERROR, RULE_TAGS_LOAD_ERROR } from '../pages/rules/translations'; -import { FetchRulesProps, RuleState, TagsState } from '../pages/rules/types'; -import { useKibana } from '../utils/kibana_react'; -import { usePluginContext } from './use_plugin_context'; - -export function useFetchRules({ - searchText, - ruleLastResponseFilter, - ruleStatusesFilter, - typesFilter, - tagsFilter, - setPage, - page, - sort, -}: FetchRulesProps) { - const { http } = useKibana().services; - const { observabilityRuleTypeRegistry } = usePluginContext(); - - const [rulesState, setRulesState] = useState({ - isLoading: false, - data: [], - error: null, - totalItemCount: 0, - }); - - const [noData, setNoData] = useState(true); - const [initialLoad, setInitialLoad] = useState(true); - const [tagsState, setTagsState] = useState({ - data: [], - error: null, - }); - const loadRuleTagsAggs = useCallback(async () => { - try { - const ruleTagsAggs = await loadRuleTags({ - http, - }); - - if (ruleTagsAggs?.ruleTags) { - setTagsState({ data: ruleTagsAggs.ruleTags, error: null }); - } - } catch (e) { - setTagsState((oldState: TagsState) => ({ ...oldState, error: RULE_TAGS_LOAD_ERROR })); - } - }, [http]); - - const fetchRules = useCallback(async () => { - setRulesState((oldState) => ({ ...oldState, isLoading: true })); - - try { - const response = await loadRules({ - http, - page, - searchText, - typesFilter: typesFilter.length > 0 ? typesFilter : observabilityRuleTypeRegistry.list(), - tagsFilter, - ruleExecutionStatusesFilter: ruleLastResponseFilter, - ruleStatusesFilter, - sort, - }); - await loadRuleTagsAggs(); - setRulesState((oldState) => ({ - ...oldState, - isLoading: false, - data: response.data, - totalItemCount: response.total, - })); - - if (!response.data?.length && page.index > 0) { - setPage({ ...page, index: 0 }); - } - const isFilterApplied = !( - isEmpty(searchText) && - isEmpty(ruleLastResponseFilter) && - isEmpty(typesFilter) && - isEmpty(tagsFilter) && - isEmpty(ruleStatusesFilter) - ); - - setNoData(response.data.length === 0 && !isFilterApplied); - } catch (_e) { - setRulesState((oldState) => ({ ...oldState, isLoading: false, error: RULES_LOAD_ERROR })); - } - setInitialLoad(false); - }, [ - http, - page, - searchText, - typesFilter, - observabilityRuleTypeRegistry, - tagsFilter, - ruleLastResponseFilter, - ruleStatusesFilter, - sort, - loadRuleTagsAggs, - setPage, - ]); - useEffect(() => { - fetchRules(); - }, [fetchRules]); - - return { - rulesState, - reload: fetchRules, - setRulesState, - noData, - initialLoad, - tagsState, - }; -} diff --git a/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts b/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts index a20e42cd37841..80a207a846d33 100644 --- a/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts +++ b/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts @@ -40,6 +40,7 @@ const triggersActionsUiStartMock = { getRuleTagBadge: jest.fn(), getRuleStatusFilter: jest.fn(), getRuleTagFilter: jest.fn(), + getRulesList: jest.fn(), ruleTypeRegistry: { has: jest.fn(), register: jest.fn(), diff --git a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx index 04519b5f5e7fe..92e19a28e3803 100644 --- a/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx +++ b/x-pack/plugins/observability/public/pages/overview/overview.stories.tsx @@ -84,7 +84,6 @@ const withCore = makeDecorator({ } as unknown as AppMountParameters, observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(), ObservabilityPageTemplate: KibanaPageTemplate, - kibanaFeatures: [], }} > {storyFn(context) as ReactNode} diff --git a/x-pack/plugins/observability/public/pages/rules/components/center_justified_spinner.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/center_justified_spinner.tsx similarity index 100% rename from x-pack/plugins/observability/public/pages/rules/components/center_justified_spinner.tsx rename to x-pack/plugins/observability/public/pages/rule_details/components/center_justified_spinner.tsx diff --git a/x-pack/plugins/observability/public/pages/rules/components/delete_modal_confirmation.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/delete_modal_confirmation.tsx similarity index 100% rename from x-pack/plugins/observability/public/pages/rules/components/delete_modal_confirmation.tsx rename to x-pack/plugins/observability/public/pages/rule_details/components/delete_modal_confirmation.tsx diff --git a/x-pack/plugins/observability/public/pages/rule_details/components/page_title.tsx b/x-pack/plugins/observability/public/pages/rule_details/components/page_title.tsx index b44eb99e44a3d..d0ad5bbc18891 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/components/page_title.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/components/page_title.tsx @@ -10,7 +10,7 @@ import { EuiText, EuiFlexGroup, EuiFlexItem, EuiBadge, EuiSpacer } from '@elasti import { PageHeaderProps } from '../types'; import { useKibana } from '../../../utils/kibana_react'; import { LAST_UPDATED_MESSAGE, CREATED_WORD, BY_WORD, ON_WORD } from '../translations'; -import { getHealthColor } from '../../rules/config'; +import { getHealthColor } from '../config'; export function PageTitle({ rule }: PageHeaderProps) { const { triggersActionsUi } = useKibana().services; diff --git a/x-pack/plugins/observability/public/pages/rule_details/config.ts b/x-pack/plugins/observability/public/pages/rule_details/config.ts index 85359447b520e..410c893aba7a3 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/config.ts +++ b/x-pack/plugins/observability/public/pages/rule_details/config.ts @@ -7,18 +7,6 @@ import { RuleExecutionStatuses } from '@kbn/alerting-plugin/common'; import { RuleType, Rule } from '@kbn/triggers-actions-ui-plugin/public'; -type Capabilities = Record; - -export type InitialRule = Partial & - Pick; - -export function hasAllPrivilege(rule: InitialRule, ruleType?: RuleType): boolean { - return ruleType?.authorizedConsumers[rule.consumer]?.all ?? false; -} - -export const hasExecuteActionsCapability = (capabilities: Capabilities) => - capabilities?.actions?.execute; - export function getHealthColor(status: RuleExecutionStatuses) { switch (status) { case 'active': @@ -33,3 +21,15 @@ export function getHealthColor(status: RuleExecutionStatuses) { return 'subdued'; } } + +type Capabilities = Record; + +export type InitialRule = Partial & + Pick; + +export function hasAllPrivilege(rule: InitialRule, ruleType?: RuleType): boolean { + return ruleType?.authorizedConsumers[rule.consumer]?.all ?? false; +} + +export const hasExecuteActionsCapability = (capabilities: Capabilities) => + capabilities?.actions?.execute; diff --git a/x-pack/plugins/observability/public/pages/rule_details/index.tsx b/x-pack/plugins/observability/public/pages/rule_details/index.tsx index e0ac4156ae099..fe6439f718ab0 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/index.tsx +++ b/x-pack/plugins/observability/public/pages/rule_details/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState, useEffect, useCallback, useRef } from 'react'; +import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react'; import { useParams } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { @@ -39,9 +39,8 @@ import { import { ALERTS_FEATURE_ID, RuleExecutionStatusErrorReasons } from '@kbn/alerting-plugin/common'; import { AlertConsumers } from '@kbn/rule-data-utils'; import { RuleDefinitionProps } from '@kbn/triggers-actions-ui-plugin/public'; -import { DeleteModalConfirmation } from '../rules/components/delete_modal_confirmation'; -import { CenterJustifiedSpinner } from '../rules/components/center_justified_spinner'; -import { OBSERVABILITY_SOLUTIONS } from '../rules/config'; +import { DeleteModalConfirmation } from './components/delete_modal_confirmation'; +import { CenterJustifiedSpinner } from './components/center_justified_spinner'; import { RuleDetailsPathParams, EVENT_LOG_LIST_TAB, ALERT_LIST_TAB } from './types'; import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; import { usePluginContext } from '../../hooks/use_plugin_context'; @@ -73,10 +72,16 @@ export function RuleDetailsPage() { } = useKibana().services; const { ruleId } = useParams(); - const { ObservabilityPageTemplate } = usePluginContext(); + const { ObservabilityPageTemplate, observabilityRuleTypeRegistry } = usePluginContext(); + + const filteredRuleTypes = useMemo( + () => observabilityRuleTypeRegistry.list(), + [observabilityRuleTypeRegistry] + ); + const { isRuleLoading, rule, errorRule, reloadRule } = useFetchRule({ ruleId, http }); const { ruleTypes } = useLoadRuleTypes({ - filteredSolutions: OBSERVABILITY_SOLUTIONS, + filteredRuleTypes, }); const [features, setFeatures] = useState(''); const [ruleType, setRuleType] = useState>(); @@ -327,7 +332,11 @@ export function RuleDetailsPage() { })} {/* Right side of Rule Summary */} - {getRuleDefinition({ rule, onEditRule: () => reloadRule() } as RuleDefinitionProps)} + {getRuleDefinition({ + filteredRuleTypes, + rule, + onEditRule: () => reloadRule(), + } as RuleDefinitionProps)}
    diff --git a/x-pack/plugins/observability/public/pages/rule_details/translations.ts b/x-pack/plugins/observability/public/pages/rule_details/translations.ts index 9efd05a549ec4..e30178e15cf47 100644 --- a/x-pack/plugins/observability/public/pages/rule_details/translations.ts +++ b/x-pack/plugins/observability/public/pages/rule_details/translations.ts @@ -41,6 +41,52 @@ export const CREATED_WORD = i18n.translate('xpack.observability.ruleDetails.crea defaultMessage: 'Created', }); +export const confirmModalText = ( + numIdsToDelete: number, + singleTitle: string, + multipleTitle: string +) => + i18n.translate('xpack.observability.rules.deleteSelectedIdsConfirmModal.descriptionText', { + defaultMessage: + "You can't recover {numIdsToDelete, plural, one {a deleted {singleTitle}} other {deleted {multipleTitle}}}.", + values: { numIdsToDelete, singleTitle, multipleTitle }, + }); + +export const confirmButtonText = ( + numIdsToDelete: number, + singleTitle: string, + multipleTitle: string +) => + i18n.translate('xpack.observability.rules.deleteSelectedIdsConfirmModal.deleteButtonLabel', { + defaultMessage: + 'Delete {numIdsToDelete, plural, one {{singleTitle}} other {# {multipleTitle}}} ', + values: { numIdsToDelete, singleTitle, multipleTitle }, + }); + +export const cancelButtonText = i18n.translate( + 'xpack.observability.rules.deleteSelectedIdsConfirmModal.cancelButtonLabel', + { + defaultMessage: 'Cancel', + } +); + +export const deleteSuccessText = ( + numSuccesses: number, + singleTitle: string, + multipleTitle: string +) => + i18n.translate('xpack.observability.rules.deleteSelectedIdsSuccessNotification.descriptionText', { + defaultMessage: + 'Deleted {numSuccesses, number} {numSuccesses, plural, one {{singleTitle}} other {{multipleTitle}}}', + values: { numSuccesses, singleTitle, multipleTitle }, + }); + +export const deleteErrorText = (numErrors: number, singleTitle: string, multipleTitle: string) => + i18n.translate('xpack.observability.rules.deleteSelectedIdsErrorNotification.descriptionText', { + defaultMessage: + 'Failed to delete {numErrors, number} {numErrors, plural, one {{singleTitle}} other {{multipleTitle}}}', + values: { numErrors, singleTitle, multipleTitle }, + }); export const ALERT_STATUS_LICENSE_ERROR = i18n.translate( 'xpack.observability.ruleDetails.ruleStatusLicenseError', { diff --git a/x-pack/plugins/observability/public/pages/rules/components/edit_rule_flyout.tsx b/x-pack/plugins/observability/public/pages/rules/components/edit_rule_flyout.tsx deleted file mode 100644 index 89dce3e1975fd..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/edit_rule_flyout.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useState, useMemo, useEffect } from 'react'; -import { useKibana } from '../../../utils/kibana_react'; -import { EditFlyoutProps } from '../types'; - -export function EditRuleFlyout({ currentRule, onSave }: EditFlyoutProps) { - const { triggersActionsUi } = useKibana().services; - const [editFlyoutVisible, setEditFlyoutVisibility] = useState(false); - - useEffect(() => { - setEditFlyoutVisibility(true); - }, [currentRule]); - const EditAlertFlyout = useMemo( - () => - triggersActionsUi.getEditAlertFlyout({ - initialRule: currentRule, - onClose: () => { - setEditFlyoutVisibility(false); - }, - onSave, - }), - [currentRule, setEditFlyoutVisibility, triggersActionsUi, onSave] - ); - return <>{editFlyoutVisible && EditAlertFlyout}; -} diff --git a/x-pack/plugins/observability/public/pages/rules/components/execution_status.tsx b/x-pack/plugins/observability/public/pages/rules/components/execution_status.tsx deleted file mode 100644 index c0c7413aa9c15..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/execution_status.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useState } from 'react'; -import { EuiHealth, EuiToolTip, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; -import { RuleExecutionStatusErrorReasons } from '@kbn/alerting-plugin/common'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { ManageLicenseModal } from './manage_license_model'; -import { getHealthColor, rulesStatusesTranslationsMapping } from '../config'; -import { RULE_STATUS_LICENSE_ERROR } from '../translations'; -import { ExecutionStatusProps } from '../types'; -import { useKibana } from '../../../utils/kibana_react'; - -export function ExecutionStatus({ executionStatus, item, licenseType }: ExecutionStatusProps) { - const { http } = useKibana().services; - const [manageLicenseModalOpts, setManageLicenseModalOpts] = useState<{ - licenseType: string; - ruleTypeId: string; - } | null>(null); - const healthColor = getHealthColor(executionStatus.status); - const tooltipMessage = - executionStatus.status === 'error' ? `Error: ${executionStatus?.error?.message}` : null; - const isLicenseError = executionStatus.error?.reason === RuleExecutionStatusErrorReasons.License; - const statusMessage = isLicenseError - ? RULE_STATUS_LICENSE_ERROR - : rulesStatusesTranslationsMapping[executionStatus.status]; - - const health = ( - - {statusMessage} - - ); - - const healthWithTooltip = tooltipMessage ? ( - - {health} - - ) : ( - health - ); - - return ( - - {healthWithTooltip} - {isLicenseError && ( - - - setManageLicenseModalOpts({ - licenseType, - ruleTypeId: item.ruleTypeId, - }) - } - > - - - - )} - {manageLicenseModalOpts && ( - { - window.open(`${http.basePath.get()}/app/management/stack/license_management`, '_blank'); - setManageLicenseModalOpts(null); - }} - onCancel={() => setManageLicenseModalOpts(null)} - /> - )} - - ); -} diff --git a/x-pack/plugins/observability/public/pages/rules/components/last_response_filter.tsx b/x-pack/plugins/observability/public/pages/rules/components/last_response_filter.tsx deleted file mode 100644 index f74c56f7f2792..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/last_response_filter.tsx +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/* eslint-disable react/function-component-definition */ - -import React, { useEffect, useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiFilterGroup, - EuiPopover, - EuiFilterButton, - EuiFilterSelectItem, - EuiHealth, -} from '@elastic/eui'; -import { RuleExecutionStatuses, RuleExecutionStatusValues } from '@kbn/alerting-plugin/common'; -import { getHealthColor, rulesStatusesTranslationsMapping } from '../config'; -import { LastResponseFilterProps } from '../types'; - -export const LastResponseFilter: React.FunctionComponent = ({ - selectedStatuses, - onChange, -}: LastResponseFilterProps) => { - const [selectedValues, setSelectedValues] = useState(selectedStatuses); - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - - useEffect(() => { - if (onChange) { - onChange(selectedValues); - } - }, [selectedValues, onChange]); - - useEffect(() => { - setSelectedValues(selectedStatuses); - }, [selectedStatuses]); - - return ( - - setIsPopoverOpen(false)} - button={ - 0} - numActiveFilters={selectedValues.length} - numFilters={selectedValues.length} - onClick={() => setIsPopoverOpen(!isPopoverOpen)} - data-test-subj="ruleStatusFilterButton" - > - - - } - > -
    - {[...RuleExecutionStatusValues].sort().map((item: RuleExecutionStatuses) => { - const healthColor = getHealthColor(item); - return ( - { - const isPreviouslyChecked = selectedValues.includes(item); - if (isPreviouslyChecked) { - setSelectedValues(selectedValues.filter((val) => val !== item)); - } else { - setSelectedValues(selectedValues.concat(item)); - } - }} - checked={selectedValues.includes(item) ? 'on' : undefined} - data-test-subj={`ruleStatus${item}FilerOption`} - > - {rulesStatusesTranslationsMapping[item]} - - ); - })} -
    -
    -
    - ); -}; diff --git a/x-pack/plugins/observability/public/pages/rules/components/last_run.tsx b/x-pack/plugins/observability/public/pages/rules/components/last_run.tsx deleted file mode 100644 index 08bb6fb229b94..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/last_run.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import moment from 'moment'; -import { LastRunProps } from '../types'; - -export function LastRun({ date }: LastRunProps) { - return ( - <> - - - - {moment(date).fromNow()} - - - - - ); -} diff --git a/x-pack/plugins/observability/public/pages/rules/components/manage_license_model.tsx b/x-pack/plugins/observability/public/pages/rules/components/manage_license_model.tsx deleted file mode 100644 index e273c7d5a3044..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/manage_license_model.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiConfirmModal } from '@elastic/eui'; -import { capitalize } from 'lodash'; - -interface Props { - licenseType: string; - ruleTypeId: string; - onConfirm: () => void; - onCancel: () => void; -} - -export function ManageLicenseModal({ licenseType, ruleTypeId, onConfirm, onCancel }: Props) { - const licenseRequired = capitalize(licenseType); - return ( - -

    - -

    -
    - ); -} diff --git a/x-pack/plugins/observability/public/pages/rules/components/name.tsx b/x-pack/plugins/observability/public/pages/rules/components/name.tsx deleted file mode 100644 index 96418758df0a5..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/name.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiText } from '@elastic/eui'; -import { RuleNameProps } from '../types'; -import { useKibana } from '../../../utils/kibana_react'; -import { paths } from '../../../config/paths'; - -export function Name({ name, rule }: RuleNameProps) { - const { http } = useKibana().services; - const detailsLink = http.basePath.prepend(paths.observability.ruleDetails(rule.id)); - const link = ( - - - - - - {name} - - - - - - - {rule.ruleType} - - - - ); - return <>{link}; -} diff --git a/x-pack/plugins/observability/public/pages/rules/components/prompts/no_data_prompt.tsx b/x-pack/plugins/observability/public/pages/rules/components/prompts/no_data_prompt.tsx deleted file mode 100644 index bacc311357fd7..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/prompts/no_data_prompt.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FormattedMessage } from '@kbn/i18n-react'; -import React from 'react'; -import { EuiButton, EuiEmptyPrompt, EuiLink, EuiButtonEmpty, EuiPageTemplate } from '@elastic/eui'; - -export function NoDataPrompt({ - onCTAClicked, - documentationLink, -}: { - onCTAClicked: () => void; - documentationLink: string; -}) { - return ( - - - - - } - body={ -

    - -

    - } - actions={[ - - - , - - - Documentation - - , - ]} - /> -
    - ); -} diff --git a/x-pack/plugins/observability/public/pages/rules/components/prompts/no_permission_prompt.tsx b/x-pack/plugins/observability/public/pages/rules/components/prompts/no_permission_prompt.tsx deleted file mode 100644 index b32952bbc18d4..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/prompts/no_permission_prompt.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FormattedMessage } from '@kbn/i18n-react'; -import React from 'react'; -import { EuiEmptyPrompt, EuiPageTemplate } from '@elastic/eui'; - -export function NoPermissionPrompt() { - return ( - - - - - } - body={ -

    - -

    - } - /> -
    - ); -} diff --git a/x-pack/plugins/observability/public/pages/rules/components/rules_table.tsx b/x-pack/plugins/observability/public/pages/rules/components/rules_table.tsx deleted file mode 100644 index 7a860b4fc7f2f..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/rules_table.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React, { useCallback } from 'react'; -import { EuiBasicTable, EuiSpacer, EuiTableSortingType } from '@elastic/eui'; -import { RuleTableItem } from '@kbn/triggers-actions-ui-plugin/public'; -import { RulesTableProps } from '../types'; - -export interface Pagination { - index: number; - size: number; -} - -export function RulesTable({ - columns, - rules, - page, - totalItemCount, - onPageChange, - sort, - onSortChange, - isLoading, -}: RulesTableProps) { - const onChange = useCallback( - ({ - page: changedPage, - sort: changedSort, - }: { - page?: Pagination; - sort?: EuiTableSortingType['sort']; - }) => { - if (changedPage) { - onPageChange(changedPage); - } - if (changedSort) { - onSortChange(changedSort); - } - }, - [onPageChange, onSortChange] - ); - return ( -
    - - <> - - - - -
    - ); -} diff --git a/x-pack/plugins/observability/public/pages/rules/components/type_filter.tsx b/x-pack/plugins/observability/public/pages/rules/components/type_filter.tsx deleted file mode 100644 index 5f4d4666002b5..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/components/type_filter.tsx +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { Fragment, useEffect, useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiFilterGroup, - EuiPopover, - EuiFilterButton, - EuiFilterSelectItem, - EuiTitle, -} from '@elastic/eui'; - -interface TypeFilterProps { - options: Array<{ - groupName: string; - subOptions: Array<{ - value: string; - name: string; - }>; - }>; - onChange?: (selectedTags: string[]) => void; -} - -export function TypeFilter({ options, onChange }: TypeFilterProps) { - const [selectedValues, setSelectedValues] = useState([]); - const [isPopoverOpen, setIsPopoverOpen] = useState(false); - - useEffect(() => { - if (onChange) { - onChange(selectedValues); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedValues]); - - return ( - - setIsPopoverOpen(false)} - button={ - 0} - numActiveFilters={selectedValues.length} - numFilters={selectedValues.length} - onClick={() => setIsPopoverOpen(!isPopoverOpen)} - data-test-subj="ruleTypeFilterButton" - > - - - } - > -
    - {options.map((groupItem, groupIndex) => ( - - -

    {groupItem.groupName}

    -
    - {groupItem.subOptions.map((item, index) => ( - { - const isPreviouslyChecked = selectedValues.includes(item.value); - if (isPreviouslyChecked) { - setSelectedValues(selectedValues.filter((val) => val !== item.value)); - } else { - setSelectedValues(selectedValues.concat(item.value)); - } - }} - checked={selectedValues.includes(item.value) ? 'on' : undefined} - data-test-subj={`ruleType${item.value}FilterOption`} - > - {item.name} - - ))} -
    - ))} -
    -
    -
    - ); -} diff --git a/x-pack/plugins/observability/public/pages/rules/config.ts b/x-pack/plugins/observability/public/pages/rules/config.ts index de3ef1219fde7..4a87792c3c602 100644 --- a/x-pack/plugins/observability/public/pages/rules/config.ts +++ b/x-pack/plugins/observability/public/pages/rules/config.ts @@ -5,44 +5,7 @@ * 2.0. */ -import { RuleExecutionStatuses } from '@kbn/alerting-plugin/common'; -import { Rule, RuleTypeIndex, RuleType } from '@kbn/triggers-actions-ui-plugin/public'; -import { - RULE_STATUS_OK, - RULE_STATUS_ACTIVE, - RULE_STATUS_ERROR, - RULE_STATUS_PENDING, - RULE_STATUS_UNKNOWN, - RULE_STATUS_WARNING, -} from './translations'; - -export const DEFAULT_SEARCH_PAGE_SIZE: number = 25; - -export function getHealthColor(status: RuleExecutionStatuses) { - switch (status) { - case 'active': - return 'success'; - case 'error': - return 'danger'; - case 'ok': - return 'primary'; - case 'pending': - return 'accent'; - default: - return 'subdued'; - } -} - -export const rulesStatusesTranslationsMapping = { - ok: RULE_STATUS_OK, - active: RULE_STATUS_ACTIVE, - error: RULE_STATUS_ERROR, - pending: RULE_STATUS_PENDING, - unknown: RULE_STATUS_UNKNOWN, - warning: RULE_STATUS_WARNING, -}; - -export const OBSERVABILITY_SOLUTIONS = ['logs', 'uptime', 'infrastructure', 'apm']; +import { Rule, RuleType } from '@kbn/triggers-actions-ui-plugin/public'; export type InitialRule = Partial & Pick; @@ -50,25 +13,3 @@ export type InitialRule = Partial & export function hasAllPrivilege(rule: InitialRule, ruleType?: RuleType): boolean { return ruleType?.authorizedConsumers[rule.consumer]?.all ?? false; } - -export function convertRulesToTableItems( - rules: Rule[], - ruleTypeIndex: RuleTypeIndex, - canExecuteActions: boolean -) { - return rules.map((rule, index: number) => ({ - ...rule, - index, - actionsCount: rule.actions.length, - ruleType: ruleTypeIndex.get(rule.ruleTypeId)?.name ?? rule.ruleTypeId, - isEditable: - hasAllPrivilege(rule, ruleTypeIndex.get(rule.ruleTypeId)) && - (canExecuteActions || (!canExecuteActions && !rule.actions.length)), - enabledInLicense: !!ruleTypeIndex.get(rule.ruleTypeId)?.enabledInLicense, - })); -} - -type Capabilities = Record; - -export const hasExecuteActionsCapability = (capabilities: Capabilities) => - capabilities?.actions?.execute; diff --git a/x-pack/plugins/observability/public/pages/rules/index.test.tsx b/x-pack/plugins/observability/public/pages/rules/index.test.tsx index cf6fae882cad8..a9bf4aff99a83 100644 --- a/x-pack/plugins/observability/public/pages/rules/index.test.tsx +++ b/x-pack/plugins/observability/public/pages/rules/index.test.tsx @@ -12,15 +12,12 @@ import { ReactWrapper } from 'enzyme'; import { CoreStart } from '@kbn/core/public'; import { ObservabilityPublicPluginsStart } from '../../plugin'; import { RulesPage } from '.'; -import { RulesTable } from './components/rules_table'; import { kibanaStartMock } from '../../utils/kibana_react.mock'; import * as pluginContext from '../../hooks/use_plugin_context'; import { KibanaPageTemplate } from '@kbn/shared-ux-components'; import { createObservabilityRuleTypeRegistryMock } from '../../rules/observability_rule_type_registry_mock'; import { AppMountParameters } from '@kbn/core/public'; import { ALERTS_FEATURE_ID } from '@kbn/alerting-plugin/common'; -import { RuleState } from './types'; -import { Rule } from '@kbn/triggers-actions-ui-plugin/public'; const mockUseKibanaReturnValue = kibanaStartMock.startContract(); @@ -33,10 +30,6 @@ jest.mock('../../hooks/use_breadcrumbs', () => ({ useBreadcrumbs: jest.fn(), })); -jest.mock('../../hooks/use_fetch_rules', () => ({ - useFetchRules: jest.fn(), -})); - jest.mock('@kbn/triggers-actions-ui-plugin/public', () => ({ useLoadRuleTypes: jest.fn(), })); @@ -50,272 +43,11 @@ jest.spyOn(pluginContext, 'usePluginContext').mockImplementation(() => ({ plugins: {} as ObservabilityPublicPluginsStart, })); -const { useFetchRules } = jest.requireMock('../../hooks/use_fetch_rules'); const { useLoadRuleTypes } = jest.requireMock('@kbn/triggers-actions-ui-plugin/public'); -describe('empty RulesPage', () => { - let wrapper: ReactWrapper; - async function setup() { - const rulesState: RuleState = { - isLoading: false, - data: [], - error: null, - totalItemCount: 0, - }; - - useLoadRuleTypes.mockReturnValue({ - ruleTypes: [ - { - id: 'test_rule_type', - name: 'some rule type', - actionGroups: [{ id: 'default', name: 'Default' }], - recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, - actionVariables: { context: [], state: [] }, - defaultActionGroupId: 'default', - producer: ALERTS_FEATURE_ID, - minimumLicenseRequired: 'basic', - enabledInLicense: true, - authorizedConsumers: { - [ALERTS_FEATURE_ID]: { read: true, all: true }, - }, - ruleTaskTimeout: '1m', - }, - ], - }); - useFetchRules.mockReturnValue({ - rulesState, - noData: true, - tagsState: { data: [], error: null }, - }); - wrapper = mountWithIntl(); - } - it('renders empty screen', async () => { - await setup(); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - expect(wrapper.find(RulesTable).exists()).toBe(false); - expect(wrapper.find('[data-test-subj="createFirstRuleEmptyPrompt"]').exists()).toBeTruthy(); - }); - it('renders Create rule button', async () => { - await setup(); - expect(wrapper.find('EuiButton[data-test-subj="createFirstRuleButton"]')).toHaveLength(1); - }); - it('renders Documentation link', async () => { - await setup(); - expect(wrapper.find('EuiLink[data-test-subj="documentationLink"]')).toHaveLength(1); - expect( - wrapper.find('EuiLink[data-test-subj="documentationLink"]').getElement().props.href - ).toContain('create-alerts.html'); - }); -}); - -describe('empty RulesPage with show only capability', () => { - let wrapper: ReactWrapper; - async function setup() { - const rulesState: RuleState = { - isLoading: false, - data: [], - error: null, - totalItemCount: 0, - }; - const ruleTypes = [ - { - id: 'test_rule_type', - name: 'some rule type', - actionGroups: [{ id: 'default', name: 'Default' }], - recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, - actionVariables: { context: [], state: [] }, - defaultActionGroupId: 'default', - producer: ALERTS_FEATURE_ID, - minimumLicenseRequired: 'basic', - enabledInLicense: true, - authorizedConsumers: { - [ALERTS_FEATURE_ID]: { read: true, all: false }, - }, - ruleTaskTimeout: '1m', - }, - ]; - useFetchRules.mockReturnValue({ - rulesState, - noData: true, - tagsState: { data: [], error: null }, - }); - useLoadRuleTypes.mockReturnValue({ ruleTypes }); - - wrapper = mountWithIntl(); - } - - it('renders no permission screen', async () => { - await setup(); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - - expect(wrapper.find('[data-test-subj="noPermissionPrompt"]').exists()).toBeTruthy(); - }); - - it('does not render no data screen', async () => { - await setup(); - - await act(async () => { - await nextTick(); - wrapper.update(); - }); - expect(wrapper.find('[data-test-subj="createFirstRuleEmptyPrompt"]').exists()).toBeFalsy(); - }); -}); - -describe('RulesPage with items', () => { +describe('RulesPage with all capabilities', () => { let wrapper: ReactWrapper; async function setup() { - const mockedRulesData: Rule[] = [ - { - id: '1', - name: 'test rule', - tags: ['tag1'], - enabled: true, - ruleTypeId: 'test_rule_type', - schedule: { interval: '1s' }, - actions: [], - params: { name: 'test rule type name' }, - createdBy: null, - updatedBy: null, - apiKeyOwner: null, - throttle: '1m', - muteAll: false, - mutedInstanceIds: [], - createdAt: new Date(), - updatedAt: new Date(), - consumer: 'alerts', - notifyWhen: 'onActiveAlert', - executionStatus: { - status: 'active', - lastDuration: 500, - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - monitoring: { - execution: { - history: [ - { - success: true, - duration: 1000000, - timestamp: 1234567, - }, - { - success: true, - duration: 200000, - timestamp: 1234567, - }, - { - success: false, - duration: 300000, - timestamp: 1234567, - }, - ], - calculated_metrics: { - success_ratio: 0.66, - p50: 200000, - p95: 300000, - p99: 300000, - }, - }, - }, - }, - { - id: '2', - name: 'test rule ok', - tags: ['tag1'], - enabled: true, - ruleTypeId: 'test_rule_type', - schedule: { interval: '5d' }, - actions: [], - params: { name: 'test rule type name' }, - createdBy: null, - updatedBy: null, - apiKeyOwner: null, - throttle: '1m', - muteAll: false, - mutedInstanceIds: [], - createdAt: new Date(), - updatedAt: new Date(), - consumer: 'alerts', - notifyWhen: 'onActiveAlert', - executionStatus: { - status: 'ok', - lastDuration: 61000, - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - error: undefined, - }, - monitoring: { - execution: { - history: [ - { - success: true, - duration: 100000, - timestamp: 1234567, - }, - { - success: true, - duration: 500000, - timestamp: 1234567, - }, - ], - calculated_metrics: { - success_ratio: 1, - p50: 0, - p95: 100000, - p99: 500000, - }, - }, - }, - }, - { - id: '3', - name: 'test rule pending', - tags: ['tag1'], - enabled: true, - ruleTypeId: 'test_rule_type', - schedule: { interval: '5d' }, - actions: [], - params: { name: 'test rule type name' }, - createdBy: null, - updatedBy: null, - apiKeyOwner: null, - throttle: '1m', - muteAll: false, - mutedInstanceIds: [], - createdAt: new Date(), - updatedAt: new Date(), - consumer: 'alerts', - notifyWhen: 'onActiveAlert', - executionStatus: { - status: 'pending', - lastDuration: 30234, - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - monitoring: { - execution: { - history: [{ success: false, duration: 100, timestamp: 1234567 }], - calculated_metrics: { - success_ratio: 0, - }, - }, - }, - }, - ]; - - const rulesState: RuleState = { - isLoading: false, - data: mockedRulesData, - error: null, - totalItemCount: 3, - }; - const mockedRuleTypeIndex = new Map( Object.entries({ '1': { @@ -347,7 +79,7 @@ describe('RulesPage with items', () => { minimumLicenseRequired: 'basic', enabledInLicense: true, authorizedConsumers: { - [ALERTS_FEATURE_ID]: { read: true, all: false }, + [ALERTS_FEATURE_ID]: { all: true }, }, ruleTaskTimeout: '1m', }, @@ -356,7 +88,6 @@ describe('RulesPage with items', () => { ruleTypes, ruleTypeIndex: mockedRuleTypeIndex, }); - useFetchRules.mockReturnValue({ rulesState, tagsState: { data: [], error: null } }); wrapper = mountWithIntl(); await act(async () => { await nextTick(); @@ -366,155 +97,35 @@ describe('RulesPage with items', () => { it('renders table of rules', async () => { await setup(); - expect(wrapper.find(RulesTable).exists()).toBe(true); + const getRulesList = mockUseKibanaReturnValue.services.triggersActionsUi.getRulesList; + expect(getRulesList).toHaveBeenCalled(); + expect(getRulesList).toHaveBeenCalledWith( + expect.objectContaining({ + showActionFilter: false, + showCreateRuleButton: false, + ruleDetailsRoute: 'alerts/rules/:ruleId', + filteredRuleTypes: ['ruleType1', 'ruleType2'], + rulesListKey: 'observability_rulesListColumns', + visibleColumns: [ + 'ruleName', + 'ruleExecutionStatusLastDate', + 'ruleSnoozeNotify', + 'ruleExecutionStatus', + 'ruleExecutionState', + ], + }) + ); + }); + + it('renders create rule button', async () => { + await setup(); + expect(wrapper.find('[data-test-subj="createRuleButton"]').exists()).toBeTruthy(); }); }); -describe('RulesPage with items and show only capability', () => { +describe('RulesPage with show only capability', () => { let wrapper: ReactWrapper; async function setup() { - const mockedRulesData: Rule[] = [ - { - id: '1', - name: 'test rule', - tags: ['tag1'], - enabled: true, - ruleTypeId: 'test_rule_type', - schedule: { interval: '1s' }, - actions: [], - params: { name: 'test rule type name' }, - createdBy: null, - updatedBy: null, - apiKeyOwner: null, - throttle: '1m', - muteAll: false, - mutedInstanceIds: [], - createdAt: new Date(), - updatedAt: new Date(), - consumer: 'alerts', - notifyWhen: 'onActiveAlert', - executionStatus: { - status: 'active', - lastDuration: 500, - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - monitoring: { - execution: { - history: [ - { - success: true, - duration: 1000000, - timestamp: 1234567, - }, - { - success: true, - duration: 200000, - timestamp: 1234567, - }, - { - success: false, - duration: 300000, - timestamp: 1234567, - }, - ], - calculated_metrics: { - success_ratio: 0.66, - p50: 200000, - p95: 300000, - p99: 300000, - }, - }, - }, - }, - { - id: '2', - name: 'test rule ok', - tags: ['tag1'], - enabled: true, - ruleTypeId: 'test_rule_type', - schedule: { interval: '5d' }, - actions: [], - params: { name: 'test rule type name' }, - createdBy: null, - updatedBy: null, - apiKeyOwner: null, - throttle: '1m', - muteAll: false, - mutedInstanceIds: [], - createdAt: new Date(), - updatedAt: new Date(), - consumer: 'alerts', - notifyWhen: 'onActiveAlert', - executionStatus: { - status: 'ok', - lastDuration: 61000, - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - monitoring: { - execution: { - history: [ - { - success: true, - duration: 100000, - timestamp: 1234567, - }, - { - success: true, - duration: 500000, - timestamp: 1234567, - }, - ], - calculated_metrics: { - success_ratio: 1, - p50: 0, - p95: 100000, - p99: 500000, - }, - }, - }, - }, - { - id: '3', - name: 'test rule pending', - tags: ['tag1'], - enabled: true, - ruleTypeId: 'test_rule_type', - schedule: { interval: '5d' }, - actions: [], - params: { name: 'test rule type name' }, - createdBy: null, - updatedBy: null, - apiKeyOwner: null, - throttle: '1m', - muteAll: false, - mutedInstanceIds: [], - createdAt: new Date(), - updatedAt: new Date(), - consumer: 'alerts', - notifyWhen: 'onActiveAlert', - executionStatus: { - status: 'pending', - lastDuration: 30234, - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - monitoring: { - execution: { - history: [{ success: false, duration: 100, timestamp: 1234567 }], - calculated_metrics: { - success_ratio: 0, - }, - }, - }, - }, - ]; - const rulesState: RuleState = { - isLoading: false, - data: mockedRulesData, - error: null, - totalItemCount: 3, - }; - useFetchRules.mockReturnValue({ rulesState, tagsState: { data: [], error: null } }); - const mockedRuleTypeIndex = new Map( Object.entries({ '1': { @@ -558,6 +169,6 @@ describe('RulesPage with items and show only capability', () => { it('does not render create rule button', async () => { await setup(); - expect(wrapper.find('[data-test-subj="createRuleButton"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="createRuleButton"]').exists()).toBeFalsy(); }); }); diff --git a/x-pack/plugins/observability/public/pages/rules/index.tsx b/x-pack/plugins/observability/public/pages/rules/index.tsx index 43d98bb1b91b8..61b9d5d3ae3ba 100644 --- a/x-pack/plugins/observability/public/pages/rules/index.tsx +++ b/x-pack/plugins/observability/public/pages/rules/index.tsx @@ -5,153 +5,49 @@ * 2.0. */ -import React, { useState, useMemo, useCallback, useEffect } from 'react'; -import { capitalize, sortBy } from 'lodash'; -import { - EuiButton, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiButtonEmpty, - EuiText, - EuiHorizontalRule, - EuiTableSortingType, - EuiFieldSearch, -} from '@elastic/eui'; +import React, { useState, useMemo } from 'react'; +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { - deleteRules, - RuleTableItem, - RuleStatus, - enableRule, - disableRule, - snoozeRule, - useLoadRuleTypes, - unsnoozeRule, -} from '@kbn/triggers-actions-ui-plugin/public'; -import { RuleExecutionStatus, ALERTS_FEATURE_ID } from '@kbn/alerting-plugin/common'; +import { useLoadRuleTypes } from '@kbn/triggers-actions-ui-plugin/public'; +import type { RulesListVisibleColumns } from '@kbn/triggers-actions-ui-plugin/public'; +import { ALERTS_FEATURE_ID } from '@kbn/alerting-plugin/common'; + import { usePluginContext } from '../../hooks/use_plugin_context'; import { Provider, rulesPageStateContainer, useRulesPageStateContainer } from './state_container'; import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; import { useKibana } from '../../utils/kibana_react'; -import { useFetchRules } from '../../hooks/use_fetch_rules'; -import { RulesTable } from './components/rules_table'; -import { Name } from './components/name'; -import { LastResponseFilter } from './components/last_response_filter'; -import { TypeFilter } from './components/type_filter'; -import { ExecutionStatus } from './components/execution_status'; -import { LastRun } from './components/last_run'; -import { EditRuleFlyout } from './components/edit_rule_flyout'; -import { DeleteModalConfirmation } from './components/delete_modal_confirmation'; -import { NoDataPrompt } from './components/prompts/no_data_prompt'; -import { NoPermissionPrompt } from './components/prompts/no_permission_prompt'; -import { CenterJustifiedSpinner } from './components/center_justified_spinner'; -import { Pagination } from './types'; -import { - DEFAULT_SEARCH_PAGE_SIZE, - convertRulesToTableItems, - OBSERVABILITY_SOLUTIONS, - hasExecuteActionsCapability, -} from './config'; -import { - LAST_RESPONSE_COLUMN_TITLE, - LAST_RUN_COLUMN_TITLE, - RULE_COLUMN_TITLE, - STATUS_COLUMN_TITLE, - ACTIONS_COLUMN_TITLE, - EDIT_ACTION_ARIA_LABEL, - EDIT_ACTION_TOOLTIP, - DELETE_ACTION_TOOLTIP, - DELETE_ACTION_ARIA_LABEL, - RULES_PAGE_TITLE, - RULES_BREADCRUMB_TEXT, - RULES_SINGLE_TITLE, - RULES_PLURAL_TITLE, - SEARCH_PLACEHOLDER, -} from './translations'; -const ENTER_KEY = 13; +import { RULES_PAGE_TITLE, RULES_BREADCRUMB_TEXT } from './translations'; -function RulesPage() { - const { ObservabilityPageTemplate, kibanaFeatures } = usePluginContext(); - const { - http, - docLinks, - triggersActionsUi, - application: { capabilities }, - notifications: { toasts }, - } = useKibana().services; - const documentationLink = docLinks.links.observability.createAlerts; - const ruleTypeRegistry = triggersActionsUi.ruleTypeRegistry; - const canExecuteActions = hasExecuteActionsCapability(capabilities); - const [page, setPage] = useState({ index: 0, size: DEFAULT_SEARCH_PAGE_SIZE }); - const [sort, setSort] = useState['sort']>({ - field: 'name', - direction: 'asc', - }); - const [inputText, setInputText] = useState(); - const [searchText, setSearchText] = useState(); - const [tagsFilter, setTagsFilter] = useState([]); - const [typesFilter, setTypesFilter] = useState([]); - const { lastResponse, setLastResponse } = useRulesPageStateContainer(); - const { status, setStatus } = useRulesPageStateContainer(); - const [currentRuleToEdit, setCurrentRuleToEdit] = useState(null); - const [rulesToDelete, setRulesToDelete] = useState([]); - const [createRuleFlyoutVisibility, setCreateRuleFlyoutVisibility] = useState(false); - const [tagPopoverOpenIndex, setTagPopoverOpenIndex] = useState(-1); +const RULES_LIST_COLUMNS_KEY = 'observability_rulesListColumns'; +const RULES_LIST_COLUMNS: RulesListVisibleColumns[] = [ + 'ruleName', + 'ruleExecutionStatusLastDate', + 'ruleSnoozeNotify', + 'ruleExecutionStatus', + 'ruleExecutionState', +]; - const isRuleTypeEditableInContext = (ruleTypeId: string) => - ruleTypeRegistry.has(ruleTypeId) ? !ruleTypeRegistry.get(ruleTypeId).requiresAppContext : false; +function RulesPage() { + const { ObservabilityPageTemplate, observabilityRuleTypeRegistry } = usePluginContext(); + const { http, docLinks, triggersActionsUi } = useKibana().services; - const onRuleEdit = (ruleItem: RuleTableItem) => { - setCurrentRuleToEdit(ruleItem); - }; + const documentationLink = docLinks.links.observability.createAlerts; - const { rulesState, setRulesState, reload, noData, initialLoad, tagsState } = useFetchRules({ - searchText, - ruleLastResponseFilter: lastResponse, - ruleStatusesFilter: status, - typesFilter, - tagsFilter, - page, - setPage, - sort, - }); - const { data: rules, totalItemCount, error } = rulesState; - const { data: tags, error: tagsError } = tagsState; + const filteredRuleTypes = useMemo( + () => observabilityRuleTypeRegistry.list(), + [observabilityRuleTypeRegistry] + ); - const { ruleTypeIndex, ruleTypes } = useLoadRuleTypes({ - filteredSolutions: OBSERVABILITY_SOLUTIONS, + const { status, setStatus, lastResponse, setLastResponse } = useRulesPageStateContainer(); + const [createRuleFlyoutVisibility, setCreateRuleFlyoutVisibility] = useState(false); + const [refresh, setRefresh] = useState(new Date()); + const { ruleTypes } = useLoadRuleTypes({ + filteredRuleTypes, }); const authorizedRuleTypes = [...ruleTypes.values()]; - const getProducerFeatureName = (producer: string) => { - return kibanaFeatures?.find((featureItem) => featureItem.id === producer)?.name; - }; - - const groupRuleTypesByProducer = () => { - return authorizedRuleTypes.reduce( - ( - result: Record< - string, - Array<{ - value: string; - name: string; - }> - >, - ruleType - ) => { - const producer = ruleType.producer; - (result[producer] = result[producer] || []).push({ - value: ruleType.id, - name: ruleType.name, - }); - return result; - }, - {} - ); - }; const authorizedToCreateAnyRules = authorizedRuleTypes.some( (ruleType) => ruleType.authorizedConsumers[ALERTS_FEATURE_ID]?.all ); @@ -168,276 +64,54 @@ function RulesPage() { }, ]); - useEffect(() => { - if (tagsError) { - toasts.addDanger({ - title: tagsError, - }); - } - if (error) - toasts.addDanger({ - title: error, - }); - }, [tagsError, error, toasts]); - - const getRulesTableColumns = () => { - return [ - { - field: 'name', - name: RULE_COLUMN_TITLE, - sortable: true, - truncateText: true, - width: '30%', - 'data-test-subj': 'rulesTableCell-name', - render: (name: string, rule: RuleTableItem) => , - }, - { - field: 'tags', - name: '', - sortable: false, - width: '50px', - 'data-test-subj': 'rulesTableCell-tagsPopover', - render: (ruleTags: string[], item: RuleTableItem) => { - return ruleTags.length > 0 - ? triggersActionsUi.getRuleTagBadge<'default'>({ - isOpen: tagPopoverOpenIndex === item.index, - tags: ruleTags, - onClick: () => setTagPopoverOpenIndex(item.index), - onClose: () => setTagPopoverOpenIndex(-1), - }) - : null; - }, - }, - { - field: 'executionStatus.lastExecutionDate', - name: LAST_RUN_COLUMN_TITLE, - sortable: true, - render: (date: Date) => , - }, - { - field: 'executionStatus.status', - name: LAST_RESPONSE_COLUMN_TITLE, - sortable: true, - truncateText: false, - width: '120px', - 'data-test-subj': 'rulesTableCell-status', - render: (_executionStatus: RuleExecutionStatus, item: RuleTableItem) => ( - - ), - }, - { - field: 'enabled', - name: STATUS_COLUMN_TITLE, - sortable: true, - 'data-test-subj': 'rulesTableCell-ContextStatus', - render: (_enabled: boolean, item: RuleTableItem) => { - return triggersActionsUi.getRuleStatusDropdown({ - rule: item, - enableRule: async () => await enableRule({ http, id: item.id }), - disableRule: async () => await disableRule({ http, id: item.id }), - onRuleChanged: () => reload(), - isEditable: item.isEditable && isRuleTypeEditableInContext(item.ruleTypeId), - snoozeRule: async (snoozeSchedule) => { - await snoozeRule({ http, id: item.id, snoozeSchedule }); - }, - unsnoozeRule: async (scheduleIds) => - await unsnoozeRule({ http, id: item.id, scheduleIds }), - }); - }, - }, - { - name: ACTIONS_COLUMN_TITLE, - width: '10%', - render(item: RuleTableItem) { - return ( - - - - - onRuleEdit(item)} - iconType={'pencil'} - aria-label={EDIT_ACTION_ARIA_LABEL} - /> - - - setRulesToDelete([item.id])} - iconType={'trash'} - aria-label={DELETE_ACTION_ARIA_LABEL} - /> - - - - - ); - }, - }, - ]; - }; - const CreateRuleFlyout = useMemo( () => triggersActionsUi.getAddAlertFlyout({ consumer: ALERTS_FEATURE_ID, onClose: () => { setCreateRuleFlyoutVisibility(false); - reload(); }, - filteredSolutions: OBSERVABILITY_SOLUTIONS, + onSave: () => { + setRefresh(new Date()); + return Promise.resolve(); + }, + filteredRuleTypes, }), // eslint-disable-next-line react-hooks/exhaustive-deps - [] + [filteredRuleTypes] ); - const setRuleStatusFilter = useCallback( - (ids: RuleStatus[]) => { - setStatus(ids); - }, - [setStatus] - ); - - const setExecutionStatusFilter = useCallback( - (ids: string[]) => { - setLastResponse(ids); - }, - [setLastResponse] - ); - - const getRulesTable = () => { - if (noData && !rulesState.isLoading) { - return authorizedToCreateAnyRules ? ( - setCreateRuleFlyoutVisibility(true)} - /> - ) : ( - - ); - } - if (initialLoad) { - return ; - } - + const getRulesTable = useMemo(() => { return ( <> - - - { - setInputText(e.target.value); - if (e.target.value === '') { - setSearchText(e.target.value); - } - }} - onKeyUp={(e) => { - if (e.keyCode === ENTER_KEY) { - setSearchText(inputText); - } - }} - placeholder={SEARCH_PLACEHOLDER} - /> - - - setTypesFilter(types)} - options={sortBy(Object.entries(groupRuleTypesByProducer())).map( - ([groupName, ruleTypesOptions]) => ({ - groupName: getProducerFeatureName(groupName) ?? capitalize(groupName), - subOptions: ruleTypesOptions.sort((a, b) => a.name.localeCompare(b.name)), - }) - )} - /> - - - {triggersActionsUi.getRuleTagFilter({ - tags, - selectedTags: tagsFilter, - onChange: (myTags: string[]) => setTagsFilter(myTags), - })} - - - - - - {triggersActionsUi.getRuleStatusFilter({ - selectedStatuses: status, - onChange: setRuleStatusFilter, - })} - - - - - - - - - - - - - - - - setPage(index)} - sort={sort} - onSortChange={(changedSort) => { - setSort(changedSort); - }} - /> + {triggersActionsUi.getRulesList({ + filteredRuleTypes, + showActionFilter: false, + showCreateRuleButton: false, + ruleDetailsRoute: 'alerts/rules/:ruleId', + statusFilter: status, + onStatusFilterChange: setStatus, + lastResponseFilter: lastResponse, + onLastResponseFilterChange: setLastResponse, + refresh, + rulesListKey: RULES_LIST_COLUMNS_KEY, + visibleColumns: RULES_LIST_COLUMNS, + })} ); - }; + }, [ + triggersActionsUi, + filteredRuleTypes, + status, + setStatus, + lastResponse, + setLastResponse, + refresh, + ]); return ( - { - // a new state that rule is deleted, that's the one - setRulesToDelete([]); - // this should cause the fetcher to reload the rules - reload(); - }} - onErrors={async () => { - // Refresh the rules from the server, some rules may have beend deleted - reload(); - setRulesToDelete([]); - }} - onCancel={() => { - setRulesToDelete([]); - }} - apiDeleteCall={deleteRules} - idsToDelete={rulesToDelete} - singleTitle={RULES_SINGLE_TITLE} - multipleTitle={RULES_PLURAL_TITLE} - setIsLoadingState={(isLoading: boolean) => { - setRulesState({ ...rulesState, isLoading }); - }} - /> - - {getRulesTable()} - {currentRuleToEdit && } + {getRulesTable} {createRuleFlyoutVisibility && CreateRuleFlyout} ); diff --git a/x-pack/plugins/observability/public/pages/rules/translations.ts b/x-pack/plugins/observability/public/pages/rules/translations.ts index 8484637e25e60..3287b7310c94b 100644 --- a/x-pack/plugins/observability/public/pages/rules/translations.ts +++ b/x-pack/plugins/observability/public/pages/rules/translations.ts @@ -60,56 +60,6 @@ export const LAST_RESPONSE_COLUMN_TITLE = i18n.translate( } ); -export const LAST_RUN_COLUMN_TITLE = i18n.translate( - 'xpack.observability.rules.rulesTable.columns.lastRunTitle', - { - defaultMessage: 'Last run', - } -); - -export const RULE_COLUMN_TITLE = i18n.translate( - 'xpack.observability.rules.rulesTable.columns.nameTitle', - { - defaultMessage: 'Rule', - } -); - -export const STATUS_COLUMN_TITLE = i18n.translate( - 'xpack.observability.rules.rulesTable.columns.statusTitle', - { - defaultMessage: 'Status', - } -); - -export const ACTIONS_COLUMN_TITLE = i18n.translate( - 'xpack.observability.rules.rulesTable.columns.actionsTitle', - { - defaultMessage: 'Actions', - } -); - -export const EDIT_ACTION_ARIA_LABEL = i18n.translate( - 'xpack.observability.rules.rulesTable.columns.editAriaLabel', - { defaultMessage: 'Edit' } -); - -export const EDIT_ACTION_TOOLTIP = i18n.translate( - 'xpack.observability.rules.rulesTable.columns.editButtonTooltip', - { - defaultMessage: 'Edit', - } -); - -export const DELETE_ACTION_TOOLTIP = i18n.translate( - 'xpack.observability.rules.rulesTable.columns.deleteButtonTooltip', - { defaultMessage: 'Delete' } -); - -export const DELETE_ACTION_ARIA_LABEL = i18n.translate( - 'xpack.observability.rules.rulesTable.columns.deleteAriaLabel', - { defaultMessage: 'Delete' } -); - export const RULES_PAGE_TITLE = i18n.translate('xpack.observability.rulesTitle', { defaultMessage: 'Rules', }); @@ -132,75 +82,9 @@ export const RULE_TAGS_LOAD_ERROR = i18n.translate( } ); -export const RULES_SINGLE_TITLE = i18n.translate( - 'xpack.observability.rules.rulesTable.singleTitle', - { - defaultMessage: 'rule', - } -); - -export const RULES_PLURAL_TITLE = i18n.translate( - 'xpack.observability.rules.rulesTable.pluralTitle', - { - defaultMessage: 'rules', - } -); - -export const SEARCH_PLACEHOLDER = i18n.translate( - 'xpack.observability.rules.searchPlaceholderTitle', - { defaultMessage: 'Search' } -); - export const RULES_CHANGE_STATUS = i18n.translate( 'xpack.observability.rules.rulesTable.changeStatusAriaLabel', { defaultMessage: 'Change status', } ); - -export const confirmModalText = ( - numIdsToDelete: number, - singleTitle: string, - multipleTitle: string -) => - i18n.translate('xpack.observability.rules.deleteSelectedIdsConfirmModal.descriptionText', { - defaultMessage: - "You can't recover {numIdsToDelete, plural, one {a deleted {singleTitle}} other {deleted {multipleTitle}}}.", - values: { numIdsToDelete, singleTitle, multipleTitle }, - }); - -export const confirmButtonText = ( - numIdsToDelete: number, - singleTitle: string, - multipleTitle: string -) => - i18n.translate('xpack.observability.rules.deleteSelectedIdsConfirmModal.deleteButtonLabel', { - defaultMessage: - 'Delete {numIdsToDelete, plural, one {{singleTitle}} other {# {multipleTitle}}} ', - values: { numIdsToDelete, singleTitle, multipleTitle }, - }); - -export const cancelButtonText = i18n.translate( - 'xpack.observability.rules.deleteSelectedIdsConfirmModal.cancelButtonLabel', - { - defaultMessage: 'Cancel', - } -); - -export const deleteSuccessText = ( - numSuccesses: number, - singleTitle: string, - multipleTitle: string -) => - i18n.translate('xpack.observability.rules.deleteSelectedIdsSuccessNotification.descriptionText', { - defaultMessage: - 'Deleted {numSuccesses, number} {numSuccesses, plural, one {{singleTitle}} other {{multipleTitle}}}', - values: { numSuccesses, singleTitle, multipleTitle }, - }); - -export const deleteErrorText = (numErrors: number, singleTitle: string, multipleTitle: string) => - i18n.translate('xpack.observability.rules.deleteSelectedIdsErrorNotification.descriptionText', { - defaultMessage: - 'Failed to delete {numErrors, number} {numErrors, plural, one {{singleTitle}} other {{multipleTitle}}}', - values: { numErrors, singleTitle, multipleTitle }, - }); diff --git a/x-pack/plugins/observability/public/pages/rules/types.ts b/x-pack/plugins/observability/public/pages/rules/types.ts deleted file mode 100644 index f7abdc6fd274e..0000000000000 --- a/x-pack/plugins/observability/public/pages/rules/types.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { Dispatch, SetStateAction } from 'react'; -import { EuiTableSortingType, EuiBasicTableColumn } from '@elastic/eui'; -import { RuleExecutionStatus } from '@kbn/alerting-plugin/common'; -import { RuleTableItem, Rule, RuleStatus } from '@kbn/triggers-actions-ui-plugin/public'; - -export interface LastResponseFilterProps { - selectedStatuses: string[]; - onChange?: (selectedRuleStatusesIds: string[]) => void; -} - -export interface ExecutionStatusProps { - executionStatus: RuleExecutionStatus; - item: RuleTableItem; - licenseType: string; -} - -export interface LastRunProps { - date: Date; -} - -export interface RuleNameProps { - name: string; - rule: RuleTableItem; -} - -export interface EditFlyoutProps { - currentRule: RuleTableItem; - onSave: () => Promise; -} - -export interface Pagination { - index: number; - size: number; -} - -export interface FetchRulesProps { - searchText: string | undefined; - ruleLastResponseFilter: string[]; - ruleStatusesFilter: RuleStatus[]; - typesFilter: string[]; - tagsFilter: string[]; - page: Pagination; - setPage: Dispatch>; - sort: EuiTableSortingType['sort']; -} - -export interface RulesTableProps { - columns: Array>; - rules: RuleTableItem[]; - page: Pagination; - totalItemCount: number; - onPageChange: (changedPage: Pagination) => void; - sort: EuiTableSortingType['sort']; - onSortChange: (changedSort: EuiTableSortingType['sort']) => void; - isLoading: boolean; -} - -export interface RuleState { - isLoading: boolean; - data: Rule[]; - error: string | null; - totalItemCount: number; -} - -export interface TagsState { - data: string[]; - error: string | null; -} diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 39387b1f65f51..12821c8acb8fd 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -23,7 +23,6 @@ import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plu import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; -import type { FeaturesPluginStart } from '@kbn/features-plugin/public'; import type { HomePublicPluginSetup, HomePublicPluginStart } from '@kbn/home-plugin/public'; import { CasesDeepLinkId, CasesUiStart, getCasesDeepLinks } from '@kbn/cases-plugin/public'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; @@ -32,9 +31,12 @@ import { TriggersAndActionsUIPublicPluginSetup, TriggersAndActionsUIPublicPluginStart, } from '@kbn/triggers-actions-ui-plugin/public'; -import { KibanaFeature } from '@kbn/features-plugin/common'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; +import { + ActionTypeRegistryContract, + RuleTypeRegistryContract, +} from '@kbn/triggers-actions-ui-plugin/public'; import { observabilityAppId, observabilityFeatureId, casesPath } from '../common'; import { createLazyObservabilityPageTemplate } from './components/shared'; import { registerDataHandler } from './data_handler'; @@ -49,7 +51,6 @@ import { getExploratoryViewEmbeddable } from './components/shared/exploratory_vi import { createExploratoryViewUrl } from './components/shared/exploratory_view/configurations/exploratory_view_url'; import { createUseRulesLink } from './hooks/create_use_rules_link'; import getAppDataView from './utils/observability_data_views/get_app_data_view'; - export type ObservabilityPublicSetup = ReturnType; export interface ObservabilityPublicPluginsSetup { @@ -69,9 +70,9 @@ export interface ObservabilityPublicPluginsStart { dataViews: DataViewsPublicPluginStart; lens: LensPublicStart; discover: DiscoverStart; - features: FeaturesPluginStart; - kibanaFeatures: KibanaFeature[]; sharedUX: SharedUXPluginStart; + ruleTypeRegistry: RuleTypeRegistryContract; + actionTypeRegistry: ActionTypeRegistryContract; } export type ObservabilityPublicStart = ReturnType; @@ -152,23 +153,13 @@ export class Plugin // Get start services const [coreStart, pluginsStart, { navigation }] = await coreSetup.getStartServices(); - // The `/api/features` endpoint requires the "Global All" Kibana privilege. Users with a - // subset of this privilege are not authorized to access this endpoint and will receive a 404 - // error that causes the Alerting view to fail to load. - let kibanaFeatures: KibanaFeature[]; - try { - kibanaFeatures = await pluginsStart.features.getFeatures(); - } catch (err) { - kibanaFeatures = []; - } - + const { ruleTypeRegistry, actionTypeRegistry } = pluginsStart.triggersActionsUi; return renderApp({ core: coreStart, - plugins: pluginsStart, + plugins: { ...pluginsStart, ruleTypeRegistry, actionTypeRegistry }, appMountParameters: params, observabilityRuleTypeRegistry: this.observabilityRuleTypeRegistry, ObservabilityPageTemplate: navigation.PageTemplate, - kibanaFeatures, usageCollection: pluginsSetup.usageCollection, isDev: this.initContext.env.mode.dev, }); diff --git a/x-pack/plugins/observability/public/rules/observability_rule_type_registry_mock.ts b/x-pack/plugins/observability/public/rules/observability_rule_type_registry_mock.ts index ad1fc13b8daf2..4a2f8cfc3ba8c 100644 --- a/x-pack/plugins/observability/public/rules/observability_rule_type_registry_mock.ts +++ b/x-pack/plugins/observability/public/rules/observability_rule_type_registry_mock.ts @@ -10,6 +10,7 @@ import { ObservabilityRuleTypeRegistry } from './create_observability_rule_type_ const createRuleTypeRegistryMock = () => ({ getFormatter: () => () => 'a reason', registerFormatter: () => {}, + list: () => ['ruleType1', 'ruleType2'], }); export const createObservabilityRuleTypeRegistryMock = () => diff --git a/x-pack/plugins/observability/public/utils/test_helper.tsx b/x-pack/plugins/observability/public/utils/test_helper.tsx index 5bcc9a7bf22cb..d262f290d1fe1 100644 --- a/x-pack/plugins/observability/public/utils/test_helper.tsx +++ b/x-pack/plugins/observability/public/utils/test_helper.tsx @@ -35,7 +35,6 @@ export const render = (component: React.ReactNode) => { appMountParameters, observabilityRuleTypeRegistry, ObservabilityPageTemplate: KibanaPageTemplate, - kibanaFeatures: [], }} > {component} diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts index d82a041a4fe28..b77ceb6bf1882 100644 --- a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts @@ -8,8 +8,8 @@ // @ts-ignore import fetchMock from 'fetch-mock/es5/client'; +import { setup } from '@kbn/core-test-helpers-http-setup-browser'; import { applicationServiceMock } from '@kbn/core/public/mocks'; -import { setup } from '@kbn/core/test_helpers/http_test_setup'; import { SessionExpired } from './session_expired'; import { UnauthorizedResponseHttpInterceptor } from './unauthorized_response_http_interceptor'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/dns/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/dns/index.ts index 54c1b418f83bd..cb0fa20deb36d 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/dns/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/network/dns/index.ts @@ -28,7 +28,6 @@ export interface NetworkDnsStrategyResponse extends IEsSearchResponse { totalCount: number; pageInfo: PageInfoPaginated; inspect?: Maybe; - histogram?: Maybe; } export interface NetworkDnsEdges { @@ -45,12 +44,6 @@ export interface NetworkDnsItem { uniqueDomains?: Maybe; } -export interface MatrixOverOrdinalHistogramData { - x: string; - y: number; - g: string; -} - export interface NetworkDnsBuckets { key: string; doc_count: number; diff --git a/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts b/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts index c016a6bf45e1c..8e2bd7ba2bb4d 100644 --- a/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts @@ -97,7 +97,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlNetworkSingleIpNullKqlQuery); cy.url().should( 'include', - 'app/security/network/ip/127.0.0.1/source?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' + 'app/security/network/ip/127.0.0.1/source?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))' ); }); @@ -105,7 +105,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlNetworkSingleIpKqlQuery); cy.url().should( 'include', - '/app/security/network/ip/127.0.0.1/source?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)' + '/app/security/network/ip/127.0.0.1/source?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))' ); }); @@ -113,7 +113,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlNetworkMultipleIpNullKqlQuery); cy.url().should( 'include', - 'app/security/network/flows?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27((source.ip:%20%22127.0.0.1%22%20or%20destination.ip:%20%22127.0.0.1%22)%20or%20(source.ip:%20%22127.0.0.2%22%20or%20destination.ip:%20%22127.0.0.2%22))%27)' + 'app/security/network/flows?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27((source.ip:%20%22127.0.0.1%22%20or%20destination.ip:%20%22127.0.0.1%22)%20or%20(source.ip:%20%22127.0.0.2%22%20or%20destination.ip:%20%22127.0.0.2%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))' ); }); @@ -121,7 +121,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlNetworkMultipleIpKqlQuery); cy.url().should( 'include', - '/app/security/network/flows?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27((source.ip:%20%22127.0.0.1%22%20or%20destination.ip:%20%22127.0.0.1%22)%20or%20(source.ip:%20%22127.0.0.2%22%20or%20destination.ip:%20%22127.0.0.2%22))%20and%20((process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22))%27)' + '/app/security/network/flows?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27((source.ip:%20%22127.0.0.1%22%20or%20destination.ip:%20%22127.0.0.1%22)%20or%20(source.ip:%20%22127.0.0.2%22%20or%20destination.ip:%20%22127.0.0.2%22))%20and%20((process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))' ); }); @@ -129,7 +129,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlNetworkNullKqlQuery); cy.url().should( 'include', - '/app/security/network/flows?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' + '/app/security/network/flows?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))' ); }); @@ -138,7 +138,7 @@ describe('ml conditional links', () => { cy.url().should( 'include', - `/app/security/network/flows?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)` + `/app/security/network/flows?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))` ); }); @@ -146,7 +146,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlHostSingleHostNullKqlQuery); cy.url().should( 'include', - '/app/security/hosts/siem-windows/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' + '/app/security/hosts/siem-windows/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))' ); }); @@ -154,7 +154,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlHostSingleHostKqlQueryVariable); cy.url().should( 'include', - '/app/security/hosts/siem-windows/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' + '/app/security/hosts/siem-windows/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))' ); }); @@ -162,7 +162,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlHostSingleHostKqlQuery); cy.url().should( 'include', - '/app/security/hosts/siem-windows/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)' + '/app/security/hosts/siem-windows/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))' ); }); @@ -170,7 +170,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlHostMultiHostNullKqlQuery); cy.url().should( 'include', - '/app/security/hosts/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(host.name:%20%22siem-windows%22%20or%20host.name:%20%22siem-suricata%22)%27)' + '/app/security/hosts/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(host.name:%20%22siem-windows%22%20or%20host.name:%20%22siem-suricata%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))' ); }); @@ -178,7 +178,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlHostMultiHostKqlQuery); cy.url().should( 'include', - '/app/security/hosts/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(host.name:%20%22siem-windows%22%20or%20host.name:%20%22siem-suricata%22)%20and%20((process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22))%27)' + '/app/security/hosts/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(host.name:%20%22siem-windows%22%20or%20host.name:%20%22siem-suricata%22)%20and%20((process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))' ); }); @@ -186,7 +186,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlHostVariableHostNullKqlQuery); cy.url().should( 'include', - '/app/security/hosts/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' + '/app/security/hosts/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))' ); }); @@ -194,7 +194,7 @@ describe('ml conditional links', () => { visitWithoutDateRange(mlHostVariableHostKqlQuery); cy.url().should( 'include', - '/app/security/hosts/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)' + '/app/security/hosts/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))&query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))' ); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts b/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts index 16cbacae403c3..f30816d455070 100644 --- a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts @@ -216,7 +216,7 @@ describe('url state', () => { cy.get(NETWORK).should( 'have.attr', 'href', - `/app/security/network?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2019-08-01T20:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2019-08-01T20:33:29.186Z')))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'source.ip:%20%2210.142.0.9%22%20')` + `/app/security/network?sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'source.ip:%20%2210.142.0.9%22%20')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2019-08-01T20:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2019-08-01T20:33:29.186Z')))` ); }); @@ -229,12 +229,12 @@ describe('url state', () => { cy.get(HOSTS).should( 'have.attr', 'href', - `/app/security/hosts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'host.name:%20%22siem-kibana%22%20')` + `/app/security/hosts?sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'host.name:%20%22siem-kibana%22%20')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))` ); cy.get(NETWORK).should( 'have.attr', 'href', - `/app/security/network?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'host.name:%20%22siem-kibana%22%20')` + `/app/security/network?sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'host.name:%20%22siem-kibana%22%20')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))` ); cy.get(HOSTS_NAMES).first().should('have.text', 'siem-kibana'); @@ -245,7 +245,7 @@ describe('url state', () => { cy.get(ANOMALIES_TAB).should( 'have.attr', 'href', - "/app/security/hosts/siem-kibana/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')" + "/app/security/hosts/siem-kibana/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))&query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')" ); cy.get(BREADCRUMBS) @@ -253,14 +253,14 @@ describe('url state', () => { .should( 'have.attr', 'href', - `/app/security/hosts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')` + `/app/security/hosts?sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))` ); cy.get(BREADCRUMBS) .eq(2) .should( 'have.attr', 'href', - `/app/security/hosts/siem-kibana?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')` + `/app/security/hosts/siem-kibana?sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2023-01-01T21:33:29.186Z')))` ); }); diff --git a/x-pack/plugins/security_solution/kibana.json b/x-pack/plugins/security_solution/kibana.json index 756856c55c2f7..21684957598aa 100644 --- a/x-pack/plugins/security_solution/kibana.json +++ b/x-pack/plugins/security_solution/kibana.json @@ -42,7 +42,8 @@ "home", "telemetry", "dataViewFieldEditor", - "osquery" + "osquery", + "savedObjectsTaggingOss" ], "server": true, "ui": true, diff --git a/x-pack/plugins/security_solution/public/app/home/index.test.tsx b/x-pack/plugins/security_solution/public/app/home/index.test.tsx index 851f72a71c475..a81b6069381c2 100644 --- a/x-pack/plugins/security_solution/public/app/home/index.test.tsx +++ b/x-pack/plugins/security_solution/public/app/home/index.test.tsx @@ -20,13 +20,25 @@ import { TestProviders, } from '../../common/mock'; import { inputsActions } from '../../common/store/inputs'; -import { setSearchBarFilter } from '../../common/store/inputs/actions'; +import { + setSearchBarFilter, + setAbsoluteRangeDatePicker, + setRelativeRangeDatePicker, +} from '../../common/store/inputs/actions'; import { coreMock } from '@kbn/core/public/mocks'; import type { Filter } from '@kbn/es-query'; import { createStore } from '../../common/store'; +import type { TimeRange, UrlInputsModel } from '../../common/store/inputs/model'; +import { SecurityPageName } from '../types'; jest.mock('../../common/store/inputs/actions'); +const mockRouteSpy = jest.fn().mockReturnValue([{ pageName: 'hosts' }]); + +jest.mock('../../common/utils/route/use_route_spy', () => ({ + useRouteSpy: () => mockRouteSpy(), +})); + const DummyComponent = ({ children }: { children: React.ReactNode }) => <>{children}; const mockedUseInitializeUrlParam = jest.fn(); @@ -51,9 +63,14 @@ jest.mock('../../common/utils/global_query_string', () => { jest.mock('../../common/components/drag_and_drop/drag_drop_context_wrapper', () => ({ DragDropContextWrapper: DummyComponent, })); + jest.mock('./template_wrapper', () => ({ SecuritySolutionTemplateWrapper: DummyComponent, })); +const DATE_TIME_NOW = '2020-01-01T00:00:00.000Z'; +jest.mock('../../common/components/super_date_picker', () => ({ + formatDate: (date: string) => DATE_TIME_NOW, +})); jest.mock('react-router-dom', () => { const original = jest.requireActual('react-router-dom'); @@ -102,6 +119,9 @@ jest.mock('../../common/lib/kibana', () => { }, }, }), + KibanaServices: { + get: jest.fn(() => ({ uiSettings: { get: () => ({ from: 'now-24h', to: 'now' }) } })), + }, }; }); @@ -118,6 +138,7 @@ jest.mock('react-redux', () => { describe('HomePage', () => { beforeEach(() => { jest.clearAllMocks(); + mockedUseInitializeUrlParam.mockImplementation(jest.fn()); mockedFilterManager.setFilters([]); }); @@ -291,4 +312,211 @@ describe('HomePage', () => { ]); }); }); + + describe('Timerange', () => { + it('sets global absolute timerange initial value in the store', () => { + const timerange: TimeRange = { + from: '2020-07-07T08:20:18.966Z', + fromStr: undefined, + kind: 'absolute', + to: '2020-07-08T08:20:18.966Z', + toStr: undefined, + }; + + const state: UrlInputsModel = { + global: { + [CONSTANTS.timerange]: timerange, + linkTo: ['timeline'], + }, + timeline: { + [CONSTANTS.timerange]: timerange, + linkTo: ['global'], + }, + }; + + mockUseInitializeUrlParam(CONSTANTS.timerange, state); + + render( + + + + + + ); + + expect(setAbsoluteRangeDatePicker).toHaveBeenCalledWith({ + from: timerange.from, + to: timerange.to, + kind: timerange.kind, + id: 'global', + }); + + expect(setAbsoluteRangeDatePicker).toHaveBeenCalledWith({ + from: timerange.from, + to: timerange.to, + kind: timerange.kind, + id: 'timeline', + }); + }); + + it('sets updated relative timerange initial value in the store', () => { + const timerange: TimeRange = { + from: '2019-01-01T00:00:00.000Z', + fromStr: 'now-1d/d', + kind: 'relative', + to: '2019-01-01T00:00:00.000Z', + toStr: 'now-1d/d', + }; + + const state: UrlInputsModel = { + global: { + [CONSTANTS.timerange]: timerange, + linkTo: ['timeline'], + }, + timeline: { + [CONSTANTS.timerange]: timerange, + linkTo: ['global'], + }, + }; + + mockUseInitializeUrlParam(CONSTANTS.timerange, state); + + render( + + + + + + ); + + expect(setRelativeRangeDatePicker).toHaveBeenCalledWith({ + ...timerange, + to: DATE_TIME_NOW, + from: DATE_TIME_NOW, + id: 'global', + }); + + expect(setRelativeRangeDatePicker).toHaveBeenCalledWith({ + ...timerange, + to: DATE_TIME_NOW, + from: DATE_TIME_NOW, + id: 'timeline', + }); + }); + + it('update timerange when navigating to alerts page', () => { + const timerange: TimeRange = { + from: '2019-01-01T00:00:00.000Z', + fromStr: 'now-1d/d', + kind: 'relative', + to: '2019-01-01T00:00:00.000Z', + toStr: 'now-1d/d', + }; + + const mockstate = { + ...mockGlobalState, + inputs: { + ...mockGlobalState.inputs, + global: { + ...mockGlobalState.inputs.global, + timerange, + }, + timeline: { + ...mockGlobalState.inputs.timeline, + timerange, + }, + }, + }; + + const { storage } = createSecuritySolutionStorageMock(); + const mockStore = createStore(mockstate, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + + const TestComponent = () => ( + + + + + + ); + + const { rerender } = render(); + jest.clearAllMocks(); + + // simulate page navigation + mockRouteSpy.mockReturnValueOnce([{ pageName: SecurityPageName.alerts }]); + rerender(); + + expect(setRelativeRangeDatePicker).toHaveBeenCalledWith({ + ...timerange, + to: DATE_TIME_NOW, + from: DATE_TIME_NOW, + id: 'global', + }); + + expect(setRelativeRangeDatePicker).toHaveBeenCalledWith({ + ...timerange, + to: DATE_TIME_NOW, + from: DATE_TIME_NOW, + id: 'timeline', + }); + }); + + it('does not update timerange when navigating to hosts page', () => { + const timerange: TimeRange = { + from: '2019-01-01T00:00:00.000Z', + fromStr: 'now-1d/d', + kind: 'relative', + to: '2019-01-01T00:00:00.000Z', + toStr: 'now-1d/d', + }; + + const mockstate = { + ...mockGlobalState, + inputs: { + ...mockGlobalState.inputs, + global: { + ...mockGlobalState.inputs.global, + timerange, + }, + timeline: { + ...mockGlobalState.inputs.timeline, + timerange, + }, + }, + }; + + const { storage } = createSecuritySolutionStorageMock(); + const mockStore = createStore(mockstate, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + + const TestComponent = () => ( + + + + + + ); + + // mockedUseInitializeUrlParam.mockImplementation(jest.fn()); + const { rerender } = render(); + jest.clearAllMocks(); + + // simulate page navigation + mockRouteSpy.mockReturnValueOnce([{ pageName: SecurityPageName.hosts }]); + rerender(); + + expect(setRelativeRangeDatePicker).not.toHaveBeenCalledWith({ + ...timerange, + to: DATE_TIME_NOW, + from: DATE_TIME_NOW, + id: 'global', + }); + + expect(setRelativeRangeDatePicker).not.toHaveBeenCalledWith({ + ...timerange, + to: DATE_TIME_NOW, + from: DATE_TIME_NOW, + id: 'timeline', + }); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/app/home/index.tsx b/x-pack/plugins/security_solution/public/app/home/index.tsx index e0827887a7ebc..da3cb0c92ab9a 100644 --- a/x-pack/plugins/security_solution/public/app/home/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/index.tsx @@ -11,6 +11,7 @@ import { useLocation } from 'react-router-dom'; import type { AppLeaveHandler, AppMountParameters } from '@kbn/core/public'; import { DragDropContextWrapper } from '../../common/components/drag_and_drop/drag_drop_context_wrapper'; import { SecuritySolutionAppWrapper } from '../../common/components/page'; + import { HelpMenu } from '../../common/components/help_menu'; import { UseUrlState } from '../../common/components/url_state'; import { navTabs } from './home_navigations'; @@ -23,8 +24,7 @@ import { useUpgradeSecurityPackages } from '../../common/hooks/use_upgrade_secur import { GlobalHeader } from './global_header'; import { SecuritySolutionTemplateWrapper } from './template_wrapper'; import { ConsoleManager } from '../../management/components/console/components/console_manager'; -import { useSyncGlobalQueryString } from '../../common/utils/global_query_string'; -import { useInitSearchBarUrlParams } from '../../common/hooks/search_bar/use_init_search_bar_url_params'; +import { useUrlState } from '../../common/hooks/use_url_state'; interface HomePageProps { children: React.ReactNode; @@ -38,9 +38,8 @@ const HomePageComponent: React.FC = ({ setHeaderActionMenu, }) => { const { pathname } = useLocation(); - useSyncGlobalQueryString(); useInitSourcerer(getScopeFromPath(pathname)); - useInitSearchBarUrlParams(); + useUrlState(); const { browserFields, indexPattern } = useSourcererDataView(getScopeFromPath(pathname)); // side effect: this will attempt to upgrade the endpoint package if it is not up to date diff --git a/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.tsx b/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.tsx new file mode 100644 index 0000000000000..c59828002717d --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { Search } from '@elastic/eui'; +import { EuiInMemoryTable } from '@elastic/eui'; +import { + useSecurityDashboardsTableItems, + useDashboardsTableColumns, +} from '../../containers/dashboards/use_security_dashboards'; + +const DASHBOARDS_TABLE_SEARCH: Search = { + box: { + incremental: true, + }, +} as const; + +export const DashboardsTable: React.FC = () => { + const items = useSecurityDashboardsTableItems(); + const columns = useDashboardsTableColumns(); + + return ( + + ); +}; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts index c67bcc4ab1051..674a609e7f71a 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts @@ -79,28 +79,6 @@ const getMockObject = ( isOpen: false, graphEventId: '', }, - timerange: { - global: { - linkTo: ['timeline'], - timerange: { - from: '2019-05-16T23:10:43.696Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2019-05-17T23:10:43.697Z', - toStr: 'now', - }, - }, - timeline: { - linkTo: ['global'], - timerange: { - from: '2019-05-16T23:10:43.696Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2019-05-17T23:10:43.697Z', - toStr: 'now', - }, - }, - }, }, }; }); @@ -470,17 +448,17 @@ describe('Navigation Breadcrumbs', () => { expect(setBreadcrumbsMock).toBeCalledWith([ expect.objectContaining({ text: 'Security', - href: "securitySolutionUI/get_started?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + href: 'securitySolutionUI/get_started', onClick: expect.any(Function), }), expect.objectContaining({ text: 'Hosts', - href: "securitySolutionUI/hosts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + href: 'securitySolutionUI/hosts', onClick: expect.any(Function), }), expect.objectContaining({ text: 'siem-kibana', - href: "securitySolutionUI/hosts/siem-kibana?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", + href: 'securitySolutionUI/hosts/siem-kibana', onClick: expect.any(Function), }), { @@ -790,28 +768,26 @@ describe('Navigation Breadcrumbs', () => { chromeMock, navigateToUrlMock ); - const searchString = - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))"; expect(setBreadcrumbsMock).toBeCalledWith([ expect.objectContaining({ text: 'Security', - href: `securitySolutionUI/get_started${searchString}`, + href: 'securitySolutionUI/get_started', onClick: expect.any(Function), }), expect.objectContaining({ text: 'Explore', - href: `securitySolutionUI/explore`, + href: 'securitySolutionUI/explore', onClick: expect.any(Function), }), expect.objectContaining({ text: 'Hosts', - href: `securitySolutionUI/hosts${searchString}`, + href: 'securitySolutionUI/hosts', onClick: expect.any(Function), }), expect.objectContaining({ text: 'siem-kibana', - href: `securitySolutionUI/hosts/siem-kibana${searchString}`, + href: 'securitySolutionUI/hosts/siem-kibana', onClick: expect.any(Function), }), { diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/helpers.test.tsx new file mode 100644 index 0000000000000..bb9fa228fb018 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/navigation/helpers.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CONSTANTS } from '../url_state/constants'; +import type { SearchNavTab } from './types'; +import { TimelineTabs } from '../../../../common/types/timeline'; +import { getSearch } from './helpers'; + +describe('helpers', () => { + it('returns the search string', () => { + const serachNavTab: SearchNavTab = { urlKey: 'host', isDetailPage: false }; + const globalQueryString = 'test=123'; + const urlState = { + [CONSTANTS.timeline]: { + activeTab: TimelineTabs.query, + id: '123', + isOpen: false, + }, + }; + + expect(getSearch(serachNavTab, urlState, globalQueryString)).toEqual( + "?timeline=(activeTab:query,id:'123',isOpen:!f)&test=123" + ); + }); + + it('returns an empty string when global globalQueryString and urlState are empty', () => { + const serachNavTab: SearchNavTab = { urlKey: 'host', isDetailPage: false }; + const globalQueryString = ''; + const urlState = { + [CONSTANTS.timeline]: { + activeTab: TimelineTabs.query, + id: '', + isOpen: false, + }, + }; + + expect(getSearch(serachNavTab, urlState, globalQueryString)).toEqual(''); + }); + + it('returns the search string when global globalQueryString is empty', () => { + const serachNavTab: SearchNavTab = { urlKey: 'host', isDetailPage: false }; + const globalQueryString = ''; + const urlState = { + [CONSTANTS.timeline]: { + activeTab: TimelineTabs.query, + id: '123', + isOpen: false, + }, + }; + + expect(getSearch(serachNavTab, urlState, globalQueryString)).toEqual( + "?timeline=(activeTab:query,id:'123',isOpen:!f)" + ); + }); + + it('returns the search string when global urlState is empty', () => { + const serachNavTab: SearchNavTab = { urlKey: 'host', isDetailPage: false }; + const globalQueryString = 'test=123'; + const urlState = { + [CONSTANTS.timeline]: { + activeTab: TimelineTabs.query, + id: '', + isOpen: false, + }, + }; + + expect(getSearch(serachNavTab, urlState, globalQueryString)).toEqual('?test=123'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/helpers.ts b/x-pack/plugins/security_solution/public/common/components/navigation/helpers.ts index ba42d8478e646..b0d9573008655 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/helpers.ts @@ -8,6 +8,7 @@ import type { Location } from 'history'; import type { Filter, Query } from '@kbn/es-query'; +import { isEmpty } from 'lodash/fp'; import type { UrlInputsModel } from '../../store/inputs/model'; import type { TimelineUrl } from '../../../timelines/store/timeline/model'; import { CONSTANTS } from '../url_state/constants'; @@ -31,11 +32,11 @@ export const getSearch = ( ): string => { if (tab && tab.urlKey != null && !isAdministration(tab.urlKey)) { // TODO: Temporary code while we are migrating all query strings to global_query_string_manager - if (globalQueryString.length > 0) { - return `${getUrlStateSearch(urlState)}&${globalQueryString}`; - } else { - return getUrlStateSearch(urlState); - } + const urlStateSearch = getQueryStringFromLocation(getUrlStateSearch(urlState)); + const isNotEmpty = (e: string) => !isEmpty(e); + const search = [urlStateSearch, globalQueryString].filter(isNotEmpty).join('&'); + + return search.length > 0 ? `?${search}` : ''; } return ''; @@ -46,9 +47,7 @@ export const getUrlStateSearch = (urlState: UrlState): string => (myLocation: Location, urlKey: KeyUrlState) => { let urlStateToReplace: Filter[] | Query | TimelineUrl | UrlInputsModel | string = ''; - if (urlKey === CONSTANTS.timerange) { - urlStateToReplace = urlState[CONSTANTS.timerange]; - } else if (urlKey === CONSTANTS.timeline && urlState[CONSTANTS.timeline] != null) { + if (urlKey === CONSTANTS.timeline && urlState[CONSTANTS.timeline] != null) { const timeline = urlState[CONSTANTS.timeline]; if (timeline.id === '') { urlStateToReplace = ''; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx index b2aa13a2293ff..521f87ffd034f 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.test.tsx @@ -69,28 +69,6 @@ describe('SIEM Navigation', () => { tabName: HostsTableType.authentications, navTabs, urlState: { - [CONSTANTS.timerange]: { - global: { - [CONSTANTS.timerange]: { - from: '2019-05-16T23:10:43.696Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2019-05-17T23:10:43.697Z', - toStr: 'now', - }, - linkTo: ['timeline'], - }, - timeline: { - [CONSTANTS.timerange]: { - from: '2019-05-16T23:10:43.696Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2019-05-17T23:10:43.697Z', - toStr: 'now', - }, - linkTo: ['global'], - }, - }, [CONSTANTS.timeline]: { activeTab: TimelineTabs.query, id: '', diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx index 3526817f9d52f..41f1dd11caf49 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/index.tsx @@ -84,7 +84,6 @@ export const TabNavigationComponent: React.FC< pathName={pathName} tabName={tabName} timeline={urlState.timeline} - timerange={urlState.timerange} /> ); } diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx index 315b324bf7aca..adfb86cf311d2 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/index.test.tsx @@ -65,29 +65,6 @@ describe('Table Navigation', () => { hasMlUserPermissions: mockHasMlUserPermissions, isRiskyHostsEnabled: mockRiskyHostEnabled, }), - - [CONSTANTS.timerange]: { - global: { - [CONSTANTS.timerange]: { - from: '2019-05-16T23:10:43.696Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2019-05-17T23:10:43.697Z', - toStr: 'now', - }, - linkTo: ['timeline'], - }, - timeline: { - [CONSTANTS.timerange]: { - from: '2019-05-16T23:10:43.696Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2019-05-17T23:10:43.697Z', - toStr: 'now', - }, - linkTo: ['global'], - }, - }, [CONSTANTS.timeline]: { activeTab: TimelineTabs.query, id: '', diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts index 5b36c4fb1deef..74804bdd9ee85 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/types.ts @@ -5,7 +5,6 @@ * 2.0. */ -import type { UrlInputsModel } from '../../../store/inputs/model'; import type { CONSTANTS } from '../../url_state/constants'; import type { TimelineUrl } from '../../../../timelines/store/timeline/model'; import type { SecuritySolutionTabNavigationProps } from '../types'; @@ -15,7 +14,6 @@ export interface TabNavigationProps extends SecuritySolutionTabNavigationProps { pathName: string; pageName: string; tabName: SiemRouteType | undefined; - [CONSTANTS.timerange]: UrlInputsModel; [CONSTANTS.timeline]: TimelineUrl; } diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_get_url_search.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/use_get_url_search.tsx index 9e4b1612eebd0..00c8541784e51 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/use_get_url_search.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_get_url_search.tsx @@ -5,11 +5,12 @@ * 2.0. */ +import { isEmpty } from 'lodash/fp'; import { useCallback, useMemo } from 'react'; import { useDeepEqualSelector } from '../../hooks/use_selector'; import { useGlobalQueryString } from '../../utils/global_query_string'; -import { makeMapStateToProps } from '../url_state/helpers'; +import { getQueryStringFromLocation, makeMapStateToProps } from '../url_state/helpers'; import { getSearch, getUrlStateSearch } from './helpers'; import type { SearchNavTab } from './types'; @@ -31,11 +32,11 @@ export const useGetUrlStateQueryString = () => { const globalQueryString = useGlobalQueryString(); const getUrlStateQueryString = useCallback(() => { // TODO: Temporary code while we are migrating all query strings to global_query_string_manager - if (globalQueryString.length > 0) { - return `${getUrlStateSearch(urlState)}&${globalQueryString}`; - } + const urlStateSearch = getQueryStringFromLocation(getUrlStateSearch(urlState)); + const isNotEmpty = (e: string) => !isEmpty(e); + const search = [urlStateSearch, globalQueryString].filter(isNotEmpty).join('&'); - return getUrlStateSearch(urlState); + return search.length > 0 ? `?${search}` : ''; }, [urlState, globalQueryString]); return getUrlStateQueryString; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap index 8e752eccd06b9..22de526739c17 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap @@ -8,10 +8,10 @@ Object { "id": "main", "items": Array [ Object { - "data-href": "securitySolutionUI/get_started?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/get_started", "data-test-subj": "navigation-get_started", "disabled": false, - "href": "securitySolutionUI/get_started?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/get_started", "id": "get_started", "isSelected": false, "name": "Get started", @@ -24,20 +24,20 @@ Object { "id": "dashboards", "items": Array [ Object { - "data-href": "securitySolutionUI/overview?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/overview", "data-test-subj": "navigation-overview", "disabled": false, - "href": "securitySolutionUI/overview?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/overview", "id": "overview", "isSelected": false, "name": "Overview", "onClick": [Function], }, Object { - "data-href": "securitySolutionUI/detection_response?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/detection_response", "data-test-subj": "navigation-detection_response", "disabled": false, - "href": "securitySolutionUI/detection_response?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/detection_response", "id": "detection_response", "isSelected": false, "name": "Detection & Response", @@ -50,30 +50,30 @@ Object { "id": "detect", "items": Array [ Object { - "data-href": "securitySolutionUI/alerts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/alerts", "data-test-subj": "navigation-alerts", "disabled": false, - "href": "securitySolutionUI/alerts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/alerts", "id": "alerts", "isSelected": false, "name": "Alerts", "onClick": [Function], }, Object { - "data-href": "securitySolutionUI/rules?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/rules", "data-test-subj": "navigation-rules", "disabled": false, - "href": "securitySolutionUI/rules?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/rules", "id": "rules", "isSelected": false, "name": "Rules", "onClick": [Function], }, Object { - "data-href": "securitySolutionUI/exceptions?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/exceptions", "data-test-subj": "navigation-exceptions", "disabled": false, - "href": "securitySolutionUI/exceptions?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/exceptions", "id": "exceptions", "isSelected": false, "name": "Exception lists", @@ -86,30 +86,30 @@ Object { "id": "explore", "items": Array [ Object { - "data-href": "securitySolutionUI/hosts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/hosts", "data-test-subj": "navigation-hosts", "disabled": false, - "href": "securitySolutionUI/hosts?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/hosts", "id": "hosts", "isSelected": true, "name": "Hosts", "onClick": [Function], }, Object { - "data-href": "securitySolutionUI/network?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/network", "data-test-subj": "navigation-network", "disabled": false, - "href": "securitySolutionUI/network?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/network", "id": "network", "isSelected": false, "name": "Network", "onClick": [Function], }, Object { - "data-href": "securitySolutionUI/users?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/users", "data-test-subj": "navigation-users", "disabled": false, - "href": "securitySolutionUI/users?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/users", "id": "users", "isSelected": false, "name": "Users", @@ -122,20 +122,20 @@ Object { "id": "investigate", "items": Array [ Object { - "data-href": "securitySolutionUI/timelines?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/timelines", "data-test-subj": "navigation-timelines", "disabled": false, - "href": "securitySolutionUI/timelines?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/timelines", "id": "timelines", "isSelected": false, "name": "Timelines", "onClick": [Function], }, Object { - "data-href": "securitySolutionUI/cases?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/cases", "data-test-subj": "navigation-cases", "disabled": false, - "href": "securitySolutionUI/cases?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/cases", "id": "cases", "isSelected": false, "name": "Cases", diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.test.tsx index bc81b788a5880..0c545ec83a6ef 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.test.tsx @@ -169,10 +169,10 @@ describe('useSecuritySolutionNavigation', () => { ); expect(caseNavItem).toMatchInlineSnapshot(` Object { - "data-href": "securitySolutionUI/cases?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "data-href": "securitySolutionUI/cases", "data-test-subj": "navigation-cases", "disabled": false, - "href": "securitySolutionUI/cases?timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))", + "href": "securitySolutionUI/cases", "id": "cases", "isSelected": false, "name": "Cases", diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.tsx index 4dd00b1efc218..0243c0c926a94 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/index.tsx @@ -76,6 +76,5 @@ export const useSecuritySolutionNavigation = () => { pageName, tabName, timeline: urlState.timeline, - timerange: urlState.timerange, }); }; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/use_primary_navigation.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/use_primary_navigation.tsx index 538163acb6009..b71cd8caee292 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/use_primary_navigation.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/use_primary_navigation.tsx @@ -23,7 +23,6 @@ export const usePrimaryNavigation = ({ pageName, tabName, timeline, - timerange, }: PrimaryNavigationProps): KibanaPageTemplateProps['solutionNav'] => { const isGroupedNavigationEnabled = useIsGroupedNavigationEnabled(); const mapLocationToTab = useCallback( @@ -47,7 +46,6 @@ export const usePrimaryNavigation = ({ navTabs, selectedTabId, timeline, - timerange, }); return { diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.test.tsx index 81a12d77b39b0..f33b5b57912dd 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.test.tsx @@ -186,7 +186,7 @@ describe('SearchBarComponent', () => { expect(mockUpdateUrlParam).toHaveBeenCalledWith(savedQuery.id); }); - it('calls useUpdateUrlParam when query state changes', async () => { + it('calls useUpdateUrlParam when query query changes', async () => { const { storage } = createSecuritySolutionStorageMock(); const store = createStore(mockGlobalState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); @@ -278,4 +278,105 @@ describe('SearchBarComponent', () => { expect(mockUpdateUrlParam).toHaveBeenCalledWith(savedQuery.id); }); }); + + describe('Timerange', () => { + it('calls useUpdateUrlParam when global timerange changes', async () => { + const { storage } = createSecuritySolutionStorageMock(); + const store = createStore(mockGlobalState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + + render( + + + + ); + + jest.clearAllMocks(); + + const newTimerange = { + from: '2020-07-07T08:20:18.966Z', + fromStr: 'now-24h', + kind: 'relative', + to: '2020-07-08T08:20:18.966Z', + toStr: 'now', + }; + + store.dispatch( + inputsActions.setRelativeRangeDatePicker({ id: 'global' as InputsModelId, ...newTimerange }) + ); + + await waitFor(() => { + expect(mockUpdateUrlParam).toHaveBeenCalledWith( + expect.objectContaining({ + global: { + linkTo: ['timeline'], + timerange: newTimerange, + }, + }) + ); + }); + }); + + it('calls useUpdateUrlParam when timeline timerange changes', async () => { + const { storage } = createSecuritySolutionStorageMock(); + const store = createStore(mockGlobalState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + + render( + + + + ); + + jest.clearAllMocks(); + + const newTimerange = { + from: '2020-07-07T08:20:18.966Z', + fromStr: 'now-24h', + kind: 'relative', + to: '2020-07-08T08:20:18.966Z', + toStr: 'now', + }; + + store.dispatch( + inputsActions.setRelativeRangeDatePicker({ + id: 'timeline' as InputsModelId, + ...newTimerange, + }) + ); + + await waitFor(() => { + expect(mockUpdateUrlParam).toHaveBeenCalledWith( + expect.objectContaining({ + timeline: { + linkTo: ['global'], + timerange: newTimerange, + }, + }) + ); + }); + }); + + it('initializes timerange URL param with redux date on mount', async () => { + const { storage } = createSecuritySolutionStorageMock(); + const store = createStore(mockGlobalState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + jest.clearAllMocks(); + render( + + + + ); + + expect(mockUpdateUrlParam.mock.calls[3]).toEqual([ + { + global: { + timerange: mockGlobalState.inputs.global.timerange, + linkTo: mockGlobalState.inputs.global.linkTo, + }, + timeline: { + timerange: mockGlobalState.inputs.timeline.timerange, + linkTo: mockGlobalState.inputs.timeline.linkTo, + }, + }, + ]); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx index c2e367aed59ab..e833f1f1a5dbd 100644 --- a/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/search_bar/index.tsx @@ -19,7 +19,6 @@ import type { FilterManager, SavedQuery } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { OnTimeChangeProps } from '@elastic/eui'; - import { inputsActions } from '../../store/inputs'; import type { InputsRange } from '../../store/inputs/model'; import type { InputsModelId } from '../../store/inputs/constants'; @@ -41,6 +40,7 @@ import { usersActions } from '../../../users/store'; import { hostsActions } from '../../../hosts/store'; import { networkActions } from '../../../network/store'; import { useSyncSearchBarUrlParams } from '../../hooks/search_bar/use_sync_search_bar_url_param'; +import { useSyncTimerangeUrlParam } from '../../hooks/search_bar/use_sync_timerange_url_param'; interface SiemSearchBarProps { id: InputsModelId; @@ -92,6 +92,7 @@ export const SearchBarComponent = memo( }, [dispatch]); useSyncSearchBarUrlParams(); + useSyncTimerangeUrlParam(); useEffect(() => { if (fromStr != null && toStr != null) { diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/helpers.ts b/x-pack/plugins/security_solution/public/common/components/url_state/helpers.ts index e8719ae8d0968..f045053cd4f29 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/components/url_state/helpers.ts @@ -14,11 +14,8 @@ import { url } from '@kbn/kibana-utils-plugin/public'; import { TimelineId, TimelineTabs } from '../../../../common/types/timeline'; import { SecurityPageName } from '../../../app/types'; import type { State } from '../../store'; -import { inputsSelectors } from '../../store'; -import type { UrlInputsModel } from '../../store/inputs/model'; import type { TimelineUrl } from '../../../timelines/store/timeline/model'; import { timelineSelectors } from '../../../timelines/store/timeline'; -import { formatDate } from '../super_date_picker'; import type { NavTab } from '../navigation/types'; import type { UrlStateType } from './constants'; import { CONSTANTS } from './constants'; @@ -123,13 +120,8 @@ export const getTitle = (pageName: string, navTabs: Record): str }; export const makeMapStateToProps = () => { - const getInputsSelector = inputsSelectors.inputsSelector(); const getTimeline = timelineSelectors.getTimelineByIdSelector(); const mapStateToProps = (state: State) => { - const inputState = getInputsSelector(state); - const { linkTo: globalLinkTo, timerange: globalTimerange } = inputState.global; - const { linkTo: timelineLinkTo, timerange: timelineTimerange } = inputState.timeline; - const flyoutTimeline = getTimeline(state, TimelineId.active); const timeline = flyoutTimeline != null @@ -143,16 +135,6 @@ export const makeMapStateToProps = () => { return { urlState: { - [CONSTANTS.timerange]: { - global: { - [CONSTANTS.timerange]: globalTimerange, - linkTo: globalLinkTo, - }, - timeline: { - [CONSTANTS.timerange]: timelineTimerange, - linkTo: timelineLinkTo, - }, - }, [CONSTANTS.timeline]: timeline, }, }; @@ -161,23 +143,6 @@ export const makeMapStateToProps = () => { return mapStateToProps; }; -export const updateTimerangeUrl = ( - timeRange: UrlInputsModel, - isFirstPageLoad: boolean -): UrlInputsModel => { - if (timeRange.global.timerange.kind === 'relative') { - timeRange.global.timerange.from = formatDate(timeRange.global.timerange.fromStr); - timeRange.global.timerange.to = formatDate(timeRange.global.timerange.toStr, { roundUp: true }); - } - if (timeRange.timeline.timerange.kind === 'relative' && isFirstPageLoad) { - timeRange.timeline.timerange.from = formatDate(timeRange.timeline.timerange.fromStr); - timeRange.timeline.timerange.to = formatDate(timeRange.timeline.timerange.toStr, { - roundUp: true, - }); - } - return timeRange; -}; - export const isQueryStateEmpty = ( queryState: ValueUrlState | undefined | null, urlKey: KeyUrlState diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/url_state/index.test.tsx index 912ae85c048d9..88b75e88dd27a 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/url_state/index.test.tsx @@ -12,17 +12,9 @@ import { HookWrapper } from '../../mock'; import { SecurityPageName } from '../../../app/types'; import type { RouteSpyState } from '../../utils/route/types'; import { CONSTANTS } from './constants'; -import { - getMockPropsObj, - mockHistory, - mockSetAbsoluteRangeDatePicker, - mockSetRelativeRangeDatePicker, - testCases, - getMockProps, -} from './test_dependencies'; +import { getMockPropsObj, mockHistory, getMockProps } from './test_dependencies'; import type { UrlStateContainerPropTypes } from './types'; import { useUrlStateHooks } from './use_url_state'; -import { waitFor } from '@testing-library/react'; import { useLocation } from 'react-router-dom'; import { updateAppLinks } from '../../links'; import { links } from '../../links/app_links'; @@ -109,79 +101,6 @@ describe('UrlStateContainer', () => { }); describe('handleInitialize', () => { - describe('URL state updates redux', () => { - describe('relative timerange actions are called with correct data on component mount', () => { - test.each(testCases)( - '%o', - (page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => { - mockProps = getMockPropsObj({ - page, - examplePath, - namespaceLower, - pageName, - detailName, - }).relativeTimeSearch.undefinedQuery; - - (useLocation as jest.Mock).mockReturnValue({ - pathname: mockProps.pathName, - search: mockProps.search, - }); - - mount( useUrlStateHooks(args)} />); - - expect(mockSetRelativeRangeDatePicker.mock.calls[1][0]).toEqual({ - from: '2020-01-01T00:00:00.000Z', - fromStr: 'now-1d/d', - kind: 'relative', - to: '2020-01-01T00:00:00.000Z', - toStr: 'now-1d/d', - id: 'global', - }); - - expect(mockSetRelativeRangeDatePicker.mock.calls[0][0]).toEqual({ - from: '2020-01-01T00:00:00.000Z', - fromStr: 'now-15m', - kind: 'relative', - to: '2020-01-01T00:00:00.000Z', - toStr: 'now', - id: 'timeline', - }); - } - ); - }); - - describe('absolute timerange actions are called with correct data on component mount', () => { - test.each(testCases)( - '%o', - (page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => { - mockProps = getMockPropsObj({ page, examplePath, namespaceLower, pageName, detailName }) - .absoluteTimeSearch.undefinedQuery; - - (useLocation as jest.Mock).mockReturnValue({ - pathname: mockProps.pathName, - search: mockProps.search, - }); - - mount( useUrlStateHooks(args)} />); - - expect(mockSetAbsoluteRangeDatePicker.mock.calls[1][0]).toEqual({ - from: '2019-05-01T18:40:12.685Z', - kind: 'absolute', - to: '2019-05-02T18:40:16.082Z', - id: 'global', - }); - - expect(mockSetAbsoluteRangeDatePicker.mock.calls[0][0]).toEqual({ - from: '2019-05-01T18:40:12.685Z', - kind: 'absolute', - to: '2019-05-02T18:40:16.082Z', - id: 'timeline', - }); - } - ); - }); - }); - it("it doesn't update URL state when pathName and browserPAth are out of sync", () => { mockProps = getMockPropsObj({ page: CONSTANTS.networkPage, @@ -267,66 +186,4 @@ describe('UrlStateContainer', () => { expect(mockHistory.replace.mock.calls[0][0].search).not.toContain('timeline='); }); }); - - describe('After Initialization, keep Relative Date up to date for global only on alerts page', () => { - test.each(testCases)( - '%o', - async (page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => { - mockProps = getMockPropsObj({ - page, - examplePath, - namespaceLower, - pageName, - detailName, - }).relativeTimeSearch.undefinedQuery; - - (useLocation as jest.Mock).mockReturnValue({ - pathname: mockProps.pathName, - search: mockProps.search, - }); - - const wrapper = mount( - useUrlStateHooks(args)} /> - ); - - wrapper.setProps({ - hookProps: getMockPropsObj({ - page: CONSTANTS.hostsPage, - examplePath: '/hosts', - namespaceLower: 'hosts', - pageName: SecurityPageName.hosts, - detailName: undefined, - }).relativeTimeSearch.undefinedQuery, - }); - wrapper.update(); - - if (CONSTANTS.alertsPage === page) { - await waitFor(() => { - expect(mockSetRelativeRangeDatePicker.mock.calls[3][0]).toEqual({ - from: '2020-01-01T00:00:00.000Z', - fromStr: 'now-1d/d', - kind: 'relative', - to: '2020-01-01T00:00:00.000Z', - toStr: 'now-1d/d', - id: 'global', - }); - - expect(mockSetRelativeRangeDatePicker.mock.calls[2][0]).toEqual({ - from: 1558732849370, - fromStr: 'now-15m', - kind: 'relative', - to: 1558733749370, - toStr: 'now', - id: 'timeline', - }); - }); - } else { - await waitFor(() => { - // There is no change in url state, so that's expected we only have two actions - expect(mockSetRelativeRangeDatePicker.mock.calls.length).toEqual(2); - }); - } - } - ); - }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/index_mocked.test.tsx b/x-pack/plugins/security_solution/public/common/components/url_state/index_mocked.test.tsx index 8d9fa294c41b1..6729b19f235d7 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/index_mocked.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/url_state/index_mocked.test.tsx @@ -12,7 +12,7 @@ import { HookWrapper } from '../../mock/hook_wrapper'; import { SecurityPageName } from '../../../app/types'; import { CONSTANTS } from './constants'; -import { getFilterQuery, getMockPropsObj, mockHistory, testCases } from './test_dependencies'; +import { getFilterQuery, getMockPropsObj, mockHistory } from './test_dependencies'; import type { UrlStateContainerPropTypes } from './types'; import { useUrlStateHooks } from './use_url_state'; import { useLocation } from 'react-router-dom'; @@ -77,62 +77,6 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => }); describe('componentDidUpdate', () => { - test('timerange redux state updates the url', () => { - mockProps = getMockPropsObj({ - page: CONSTANTS.networkPage, - examplePath: '/network', - namespaceLower: 'network', - pageName: SecurityPageName.network, - detailName: undefined, - }).noSearch.definedQuery; - - (useLocation as jest.Mock).mockReturnValue({ - pathname: mockProps.pathName, - search: mockProps.search, - }); - - const wrapper = mount( - useUrlStateHooks(args)} /> - ); - - const newUrlState = { - ...mockProps.urlState, - [CONSTANTS.timerange]: { - global: { - [CONSTANTS.timerange]: { - from: '2020-07-07T08:20:18.966Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2020-07-08T08:20:18.966Z', - toStr: 'now', - }, - linkTo: ['timeline'], - }, - timeline: { - [CONSTANTS.timerange]: { - from: '2020-07-07T08:20:18.966Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2020-07-08T08:20:18.966Z', - toStr: 'now', - }, - linkTo: ['global'], - }, - }, - }; - - wrapper.setProps({ hookProps: { ...mockProps, urlState: newUrlState } }); - wrapper.update(); - expect(mockHistory.replace.mock.calls[1][0]).toStrictEqual({ - hash: '', - pathname: '/network', - search: expect.stringContaining( - "timerange=(global:(linkTo:!(timeline),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2020-07-07T08:20:18.966Z',fromStr:now-24h,kind:relative,to:'2020-07-08T08:20:18.966Z',toStr:now)))" - ), - state: '', - }); - }); - test('timelineID redux state updates the url', () => { mockProps = getMockPropsObj({ page: CONSTANTS.networkPage, @@ -163,8 +107,7 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => expect(mockHistory.replace.mock.calls[1][0]).toStrictEqual({ hash: '', pathname: '/network', - search: - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))&timeline=(id:hello_timeline_id,isOpen:!t)", + search: '?timeline=(id:hello_timeline_id,isOpen:!t)', state: '', }); }); @@ -327,121 +270,4 @@ describe('UrlStateContainer - lodash.throttle mocked to test update url', () => }); }); }); - - describe('handleInitialize', () => { - describe('Redux updates URL state', () => { - describe('Timerange url state is set when not defined on component mount', () => { - test.each(testCases)( - '%o', - (page, namespaceLower, namespaceUpper, examplePath, type, pageName, detailName) => { - mockProps = getMockPropsObj({ page, examplePath, namespaceLower, pageName, detailName }) - .noSearch.undefinedQuery; - - (useLocation as jest.Mock).mockReturnValue({ - pathname: mockProps.pathName, - search: mockProps.search, - }); - - mount( useUrlStateHooks(args)} />); - - expect(mockHistory.replace.mock.calls[0][0]).toEqual({ - hash: '', - pathname: examplePath, - search: - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))", - state: '', - }); - } - ); - - test('url state is set from redux data when location updates and initialization', () => { - mockProps = getMockPropsObj({ - page: CONSTANTS.hostsPage, - examplePath: '/hosts', - namespaceLower: 'hosts', - pageName: SecurityPageName.hosts, - detailName: undefined, - }).noSearch.undefinedQuery; - const updatedProps = getMockPropsObj({ - page: CONSTANTS.networkPage, - examplePath: '/network', - namespaceLower: 'network', - pageName: SecurityPageName.network, - detailName: undefined, - }).noSearch.definedQuery; - - (useLocation as jest.Mock).mockReturnValue({ - pathname: mockProps.pathName, - search: mockProps.search, - }); - - const wrapper = mount( - useUrlStateHooks(args)} /> - ); - - expect(mockHistory.replace.mock.calls[0][0].search).toEqual( - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))" - ); - - (useLocation as jest.Mock).mockReturnValue({ - pathname: updatedProps.pathName, - search: mockProps.search, - }); - - wrapper.setProps({ hookProps: updatedProps }); - - wrapper.update(); - - expect(mockHistory.replace.mock.calls[1][0].search).toEqual( - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))" - ); - }); - - test("doesn't update url state on administration page", () => { - mockProps = getMockPropsObj({ - page: CONSTANTS.hostsPage, - examplePath: '/hosts', - namespaceLower: 'hosts', - pageName: SecurityPageName.hosts, - detailName: undefined, - }).noSearch.undefinedQuery; - - const updatedMockProps = { - ...getMockPropsObj({ - ...mockProps, - page: CONSTANTS.unknown, - examplePath: MANAGEMENT_PATH, - namespaceLower: 'administration', - pageName: SecurityPageName.administration, - detailName: undefined, - }).noSearch.definedQuery, - }; - - (useLocation as jest.Mock).mockReturnValue({ - pathname: mockProps.pathName, - search: mockProps.search, - }); - - const wrapper = mount( - useUrlStateHooks(args)} /> - ); - - expect(mockHistory.replace.mock.calls[0][0].search).toEqual( - "?timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)),timeline:(linkTo:!(global),timerange:(from:'2019-05-16T23:10:43.696Z',fromStr:now-24h,kind:relative,to:'2019-05-17T23:10:43.697Z',toStr:now)))" - ); - - (useLocation as jest.Mock).mockReturnValue({ - pathname: updatedMockProps.pathName, - search: mockProps.search, - }); - - wrapper.setProps({ hookProps: updatedMockProps }); - - wrapper.update(); - - expect(mockHistory.replace.mock.calls[1][0].search).toEqual('?'); - }); - }); - }); - }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/initialize_redux_by_url.tsx b/x-pack/plugins/security_solution/public/common/components/url_state/initialize_redux_by_url.tsx index 187b1aadedcd4..7d404cf687f91 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/initialize_redux_by_url.tsx +++ b/x-pack/plugins/security_solution/public/common/components/url_state/initialize_redux_by_url.tsx @@ -5,23 +5,11 @@ * 2.0. */ -import { get, isEmpty } from 'lodash/fp'; -import type { Dispatch } from 'redux'; - import { useCallback, useMemo } from 'react'; import { useDispatch } from 'react-redux'; -import { inputsActions } from '../../store/actions'; -import type { InputsModelId, TimeRangeKinds } from '../../store/inputs/constants'; -import type { - UrlInputsModel, - LinkTo, - AbsoluteTimeRange, - RelativeTimeRange, -} from '../../store/inputs/model'; import type { TimelineUrl } from '../../../timelines/store/timeline/model'; import { CONSTANTS } from './constants'; import { decodeRisonUrlState } from './helpers'; -import { normalizeTimeRange } from './normalize_time_range'; import type { SetInitialStateFromUrl } from './types'; import { queryTimelineById, @@ -31,7 +19,6 @@ import { timelineActions } from '../../../timelines/store/timeline'; export const useSetInitialStateFromUrl = () => { const dispatch = useDispatch(); - const updateTimeline = useMemo(() => dispatchUpdateTimeline(dispatch), [dispatch]); const updateTimelineIsLoading = useMemo( @@ -43,10 +30,6 @@ export const useSetInitialStateFromUrl = () => { const setInitialStateFromUrl = useCallback( ({ urlStateToUpdate }: SetInitialStateFromUrl) => { urlStateToUpdate.forEach(({ urlKey, newUrlStateString }) => { - if (urlKey === CONSTANTS.timerange) { - updateTimerange(newUrlStateString, dispatch); - } - if (urlKey === CONSTANTS.timeline) { const timeline = decodeRisonUrlState(newUrlStateString); if (timeline != null && timeline.id !== '') { @@ -63,87 +46,8 @@ export const useSetInitialStateFromUrl = () => { } }); }, - [dispatch, updateTimeline, updateTimelineIsLoading] + [updateTimeline, updateTimelineIsLoading] ); return Object.freeze({ setInitialStateFromUrl, updateTimeline, updateTimelineIsLoading }); }; - -const updateTimerange = (newUrlStateString: string, dispatch: Dispatch) => { - const timerangeStateData = decodeRisonUrlState(newUrlStateString); - - const globalId: InputsModelId = 'global'; - const globalLinkTo: LinkTo = { linkTo: get('global.linkTo', timerangeStateData) }; - const globalType: TimeRangeKinds = get('global.timerange.kind', timerangeStateData); - - const timelineId: InputsModelId = 'timeline'; - const timelineLinkTo: LinkTo = { linkTo: get('timeline.linkTo', timerangeStateData) }; - const timelineType: TimeRangeKinds = get('timeline.timerange.kind', timerangeStateData); - - if (isEmpty(globalLinkTo.linkTo)) { - dispatch(inputsActions.removeGlobalLinkTo()); - } else { - dispatch(inputsActions.addGlobalLinkTo({ linkToId: 'timeline' })); - } - - if (isEmpty(timelineLinkTo.linkTo)) { - dispatch(inputsActions.removeTimelineLinkTo()); - } else { - dispatch(inputsActions.addTimelineLinkTo({ linkToId: 'global' })); - } - - if (timelineType) { - if (timelineType === 'absolute') { - const absoluteRange = normalizeTimeRange( - get('timeline.timerange', timerangeStateData) - ); - - dispatch( - inputsActions.setAbsoluteRangeDatePicker({ - ...absoluteRange, - id: timelineId, - }) - ); - } - - if (timelineType === 'relative') { - const relativeRange = normalizeTimeRange( - get('timeline.timerange', timerangeStateData) - ); - - dispatch( - inputsActions.setRelativeRangeDatePicker({ - ...relativeRange, - id: timelineId, - }) - ); - } - } - - if (globalType) { - if (globalType === 'absolute') { - const absoluteRange = normalizeTimeRange( - get('global.timerange', timerangeStateData) - ); - - dispatch( - inputsActions.setAbsoluteRangeDatePicker({ - ...absoluteRange, - id: globalId, - }) - ); - } - if (globalType === 'relative') { - const relativeRange = normalizeTimeRange( - get('global.timerange', timerangeStateData) - ); - - dispatch( - inputsActions.setRelativeRangeDatePicker({ - ...relativeRange, - id: globalId, - }) - ); - } - } -}; diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/test_dependencies.ts b/x-pack/plugins/security_solution/public/common/components/url_state/test_dependencies.ts index 2e7b1b4b99a4b..9a3dd5f7d2896 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/test_dependencies.ts +++ b/x-pack/plugins/security_solution/public/common/components/url_state/test_dependencies.ts @@ -12,8 +12,6 @@ import { inputsActions } from '../../store/actions'; import { CONSTANTS } from './constants'; import type { UrlStateContainerPropTypes, LocationTypes } from './types'; -import { networkModel } from '../../../network/store'; -import { hostsModel } from '../../../hosts/store'; import { HostsTableType } from '../../../hosts/store/model'; import { TimelineTabs } from '../../../../common/types/timeline'; @@ -91,28 +89,6 @@ export const defaultProps: UrlStateContainerPropTypes = { title: 'filebeat-*,packetbeat-*', }, urlState: { - [CONSTANTS.timerange]: { - global: { - [CONSTANTS.timerange]: { - from: '2019-05-16T23:10:43.696Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2019-05-17T23:10:43.697Z', - toStr: 'now', - }, - linkTo: ['timeline'], - }, - timeline: { - [CONSTANTS.timerange]: { - from: '2019-05-16T23:10:43.696Z', - fromStr: 'now-24h', - kind: 'relative', - to: '2019-05-17T23:10:43.697Z', - toStr: 'now', - }, - linkTo: ['global'], - }, - }, [CONSTANTS.timeline]: { activeTab: TimelineTabs.query, id: '', @@ -262,73 +238,3 @@ export const getMockPropsObj = ({ page, examplePath, pageName, detailName }: Get ), }, }); - -// silly that this needs to be an array and not an object -// https://jestjs.io/docs/en/api#testeachtable-name-fn-timeout -export const testCases: Array< - [LocationTypes, string, string, string, string | null, SecurityPageName, undefined | string] -> = [ - [ - /* page */ CONSTANTS.networkPage, - /* namespaceLower */ 'network', - /* namespaceUpper */ 'Network', - /* pathName */ '/network', - /* type */ networkModel.NetworkType.page, - /* pageName */ SecurityPageName.network, - /* detailName */ undefined, - ], - [ - /* page */ CONSTANTS.hostsPage, - /* namespaceLower */ 'hosts', - /* namespaceUpper */ 'Hosts', - /* pathName */ '/hosts', - /* type */ hostsModel.HostsType.page, - /* pageName */ SecurityPageName.hosts, - /* detailName */ undefined, - ], - [ - /* page */ CONSTANTS.hostsDetails, - /* namespaceLower */ 'hosts', - /* namespaceUpper */ 'Hosts', - /* pathName */ '/hosts/siem-es', - /* type */ hostsModel.HostsType.details, - /* pageName */ SecurityPageName.hosts, - /* detailName */ 'host-test', - ], - [ - /* page */ CONSTANTS.networkDetails, - /* namespaceLower */ 'network', - /* namespaceUpper */ 'Network', - /* pathName */ '/network/ip/100.90.80', - /* type */ networkModel.NetworkType.details, - /* pageName */ SecurityPageName.network, - /* detailName */ '100.90.80', - ], - [ - /* page */ CONSTANTS.overviewPage, - /* namespaceLower */ 'overview', - /* namespaceUpper */ 'Overview', - /* pathName */ '/overview', - /* type */ null, - /* pageName */ SecurityPageName.overview, - /* detailName */ undefined, - ], - [ - /* page */ CONSTANTS.timelinePage, - /* namespaceLower */ 'timeline', - /* namespaceUpper */ 'Timeline', - /* pathName */ '/timeline', - /* type */ null, - /* pageName */ SecurityPageName.timelines, - /* detailName */ undefined, - ], - [ - /* page */ CONSTANTS.kubernetesPage, - /* namespaceLower */ 'kubernetes', - /* namespaceUpper */ 'Kubernetes', - /* pathName */ '/kubernetes', - /* type */ null, - /* pageName */ SecurityPageName.kubernetes, - /* detailName */ undefined, - ], -]; diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/types.ts b/x-pack/plugins/security_solution/public/common/components/url_state/types.ts index 01aa4fdd2c410..6c74320ce237c 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/url_state/types.ts @@ -7,7 +7,6 @@ import type { DataViewBase } from '@kbn/es-query'; import type { FilterManager, SavedQueryService } from '@kbn/data-plugin/public'; -import type { UrlInputsModel } from '../../store/inputs/model'; import type { TimelineUrl } from '../../../timelines/store/timeline/model'; import type { RouteSpyState } from '../../utils/route/types'; import type { SecurityNav } from '../navigation/types'; @@ -15,7 +14,7 @@ import type { SecurityNav } from '../navigation/types'; import type { UrlStateType } from './constants'; import { CONSTANTS } from './constants'; -export const ALL_URL_STATE_KEYS: KeyUrlState[] = [CONSTANTS.timerange, CONSTANTS.timeline]; +export const ALL_URL_STATE_KEYS: KeyUrlState[] = [CONSTANTS.timeline]; export const isAdministration = (urlKey: UrlStateType): boolean => 'administration' === urlKey; @@ -33,7 +32,6 @@ export type LocationTypes = | CONSTANTS.unknown; export interface UrlState { - [CONSTANTS.timerange]: UrlInputsModel; [CONSTANTS.timeline]: TimelineUrl; } export type KeyUrlState = keyof UrlState; diff --git a/x-pack/plugins/security_solution/public/common/components/url_state/use_url_state.tsx b/x-pack/plugins/security_solution/public/common/components/url_state/use_url_state.tsx index 2cb24c4430427..0be72ef931101 100644 --- a/x-pack/plugins/security_solution/public/common/components/url_state/use_url_state.tsx +++ b/x-pack/plugins/security_solution/public/common/components/url_state/use_url_state.tsx @@ -25,7 +25,6 @@ import { isDetectionsPages, encodeRisonUrlState, isQueryStateEmpty, - updateTimerangeUrl, } from './helpers'; import type { UrlStateContainerPropTypes, @@ -38,7 +37,6 @@ import type { } from './types'; import { ALL_URL_STATE_KEYS, isAdministration } from './types'; import type { TimelineUrl } from '../../../timelines/store/timeline/model'; -import type { UrlInputsModel } from '../../store/inputs/model'; import { queryTimelineByIdOnUrlChange } from './query_timeline_by_id_on_url_change'; import { getLinkInfo } from '../../links'; import { useIsGroupedNavigationEnabled } from '../navigation/helpers'; @@ -97,7 +95,6 @@ export const useUrlStateHooks = ({ const stateToUpdate = getUpdateToFormatUrlStateString({ isFirstPageLoad, newUrlStateString, - updateTimerange: isDetectionsPages(pageName) || isFirstPageLoad, urlKey, }); @@ -227,12 +224,10 @@ const getQueryStringKeyValue = ({ search, urlKey }: { search: string; urlKey: st export const getUpdateToFormatUrlStateString = ({ isFirstPageLoad, newUrlStateString, - updateTimerange, urlKey, }: { isFirstPageLoad: boolean; newUrlStateString: string; - updateTimerange: boolean; urlKey: KeyUrlState; }): ReplaceStateInLocation | undefined => { if (isQueryStateEmpty(decodeRisonUrlState(newUrlStateString), urlKey)) { @@ -240,16 +235,7 @@ export const getUpdateToFormatUrlStateString = ({ urlStateToReplace: '', urlStateKey: urlKey, }; - } else if (urlKey === CONSTANTS.timerange && updateTimerange) { - const queryState = decodeRisonUrlState(newUrlStateString); - if (queryState != null && queryState.global != null) { - return { - urlStateToReplace: updateTimerangeUrl(queryState, isFirstPageLoad), - urlStateKey: urlKey, - }; - } } - return undefined; }; const isTimelinePresentInUrlStateString = (urlStateString: string, timeline: TimelineUrl) => { diff --git a/x-pack/plugins/security_solution/public/common/containers/dashboards/translations.ts b/x-pack/plugins/security_solution/public/common/containers/dashboards/translations.ts new file mode 100644 index 0000000000000..58254aa8fe9f6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/containers/dashboards/translations.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const DASHBOARD_TITLE = i18n.translate('xpack.securitySolution.dashboards.title', { + defaultMessage: 'Title', +}); + +export const DASHBOARDS_DESCRIPTION = i18n.translate( + 'xpack.securitySolution.dashboards.description', + { + defaultMessage: 'Description', + } +); diff --git a/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards.test.tsx b/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards.test.tsx new file mode 100644 index 0000000000000..e626ee8863f18 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards.test.tsx @@ -0,0 +1,203 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { renderHook, act } from '@testing-library/react-hooks'; +import { render } from '@testing-library/react'; +import type { DashboardStart } from '@kbn/dashboard-plugin/public'; +import { EuiBasicTable } from '@elastic/eui'; +import { useKibana } from '../../lib/kibana'; +import { TestProviders } from '../../mock/test_providers'; +import type { DashboardTableItem } from './use_security_dashboards'; +import { + useDashboardsTableColumns, + useSecurityDashboardsTableItems, +} from './use_security_dashboards'; + +jest.mock('../../lib/kibana'); + +const TAG_ID = 'securityTagId'; +const basicResponse: DashboardTableItem[] = [ + { + id: 'dashboardId1', + type: 'dashboard', + attributes: { + title: 'title1', + description: 'description1', + }, + references: [{ type: 'tag', id: TAG_ID, name: 'tagName' }], + }, + { + id: 'dashboardId2', + type: 'dashboard', + attributes: { + title: 'title2', + description: 'description2', + }, + references: [{ type: 'tag', id: TAG_ID, name: 'tagName' }], + }, +]; + +const renderUseSecurityDashboardsTableItems = async () => { + const renderedHook = renderHook(() => useSecurityDashboardsTableItems(), { + wrapper: TestProviders, + }); + await act(async () => { + // needed to let dashboard items to be updated from saved objects response + await renderedHook.waitForNextUpdate(); + }); + return renderedHook; +}; + +const renderUseDashboardsTableColumns = () => + renderHook(() => useDashboardsTableColumns(), { + wrapper: TestProviders, + }); + +describe('Security Dashboards hooks', () => { + const mockSavedObjectsFind = useKibana().services.savedObjects.client.find as jest.Mock; + mockSavedObjectsFind.mockImplementation(async (req) => { + if (req.type === 'tag') { + return { savedObjects: [{ id: TAG_ID }] }; + } else if (req.type === 'dashboard') { + return { savedObjects: basicResponse }; + } + return { savedObjects: [] }; + }); + + const mockGetRedirectUrl = jest.fn(() => '/path'); + useKibana().services.dashboard = { + locator: { getRedirectUrl: mockGetRedirectUrl }, + } as unknown as DashboardStart; + + const mockTaggingGetTableColumnDefinition = useKibana().services.savedObjectsTagging?.ui + .getTableColumnDefinition as jest.Mock; + const tagsColumn = { + field: 'id', // set existing field to prevent test error + name: 'Tags', + 'data-test-subj': 'dashboard-tags-field', + }; + mockTaggingGetTableColumnDefinition.mockReturnValue(tagsColumn); + + afterEach(() => { + mockTaggingGetTableColumnDefinition.mockClear(); + mockGetRedirectUrl.mockClear(); + mockSavedObjectsFind.mockClear(); + }); + + describe('useSecurityDashboardsTableItems', () => { + afterEach(() => { + mockSavedObjectsFind.mockClear(); + }); + + it('should request when renders', async () => { + await renderUseSecurityDashboardsTableItems(); + + expect(mockSavedObjectsFind).toHaveBeenCalledTimes(2); + expect(mockSavedObjectsFind).toHaveBeenCalledWith( + expect.objectContaining({ type: 'tag', search: 'security' }) + ); + expect(mockSavedObjectsFind).toHaveBeenCalledWith( + expect.objectContaining({ type: 'dashboard', hasReference: { id: TAG_ID, type: 'tag' } }) + ); + }); + + it('should not re-request when re-rendered', async () => { + const { rerender } = await renderUseSecurityDashboardsTableItems(); + + expect(mockSavedObjectsFind).toHaveBeenCalledTimes(2); + act(() => rerender()); + expect(mockSavedObjectsFind).toHaveBeenCalledTimes(2); + }); + + it('returns a memoized value', async () => { + const { result, rerender } = await renderUseSecurityDashboardsTableItems(); + + const result1 = result.current; + act(() => rerender()); + const result2 = result.current; + + expect(result1).toBe(result2); + }); + + it('should return dashboard items', async () => { + const { result } = await renderUseSecurityDashboardsTableItems(); + + const [dashboard1, dashboard2] = basicResponse; + expect(result.current).toStrictEqual([ + { + ...dashboard1, + title: dashboard1.attributes.title, + description: dashboard1.attributes.description, + }, + { + ...dashboard2, + title: dashboard2.attributes.title, + description: dashboard2.attributes.description, + }, + ]); + }); + }); + + describe('useDashboardsTableColumns', () => { + it('should call getTableColumnDefinition to get tags column', () => { + renderUseDashboardsTableColumns(); + expect(mockTaggingGetTableColumnDefinition).toHaveBeenCalled(); + }); + + it('should return dashboard columns', () => { + const { result } = renderUseDashboardsTableColumns(); + + expect(result.current).toEqual([ + expect.objectContaining({ + field: 'title', + name: 'Title', + }), + expect.objectContaining({ + field: 'description', + name: 'Description', + }), + expect.objectContaining(tagsColumn), + ]); + }); + + it('returns a memoized value', async () => { + const { result, rerender } = await renderUseSecurityDashboardsTableItems(); + + const result1 = result.current; + act(() => rerender()); + const result2 = result.current; + + expect(result1).toBe(result2); + }); + }); + + it('should render a table with consistent items and columns', async () => { + const { result: itemsResult } = await renderUseSecurityDashboardsTableItems(); + const { result: columnsResult } = renderUseDashboardsTableColumns(); + + const result = render( + , + { + wrapper: TestProviders, + } + ); + + expect(result.getAllByText('Title').length).toBeGreaterThan(0); + expect(result.getAllByText('Description').length).toBeGreaterThan(0); + expect(result.getAllByText('Tags').length).toBeGreaterThan(0); + + expect(result.getByText('title1')).toBeInTheDocument(); + expect(result.getByText('description1')).toBeInTheDocument(); + expect(result.getByText('title2')).toBeInTheDocument(); + expect(result.getByText('description2')).toBeInTheDocument(); + + expect(result.queryAllByTestId('dashboard-title-field')).toHaveLength(2); + expect(result.queryAllByTestId('dashboard-description-field')).toHaveLength(2); + expect(result.queryAllByTestId('dashboard-tags-field')).toHaveLength(2); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards.tsx b/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards.tsx new file mode 100644 index 0000000000000..19f05918d5278 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { MouseEventHandler } from 'react'; +import React, { useState, useEffect, useMemo, useCallback } from 'react'; +import type { EuiBasicTableColumn } from '@elastic/eui'; +import type { SavedObjectAttributes } from '@kbn/securitysolution-io-ts-alerting-types'; +import type { SavedObjectsClientContract, SavedObject } from '@kbn/core/public'; +import { LinkAnchor } from '../../components/links'; +import { useKibana, useNavigateTo } from '../../lib/kibana'; +import * as i18n from './translations'; + +export interface DashboardTableItem extends SavedObject { + title?: string; + description?: string; +} + +const SECURITY_TAG_NAME = 'security' as const; +const EMPTY_DESCRIPTION = '-' as const; + +const getSecurityDashboardItems = async ( + savedObjectsClient: SavedObjectsClientContract +): Promise => { + if (savedObjectsClient) { + const tagResponse = await savedObjectsClient.find({ + type: 'tag', + searchFields: ['name'], + search: SECURITY_TAG_NAME, + }); + + const tagId = tagResponse.savedObjects[0]?.id; + + if (tagId) { + const dashboardsResponse = await savedObjectsClient.find({ + type: 'dashboard', + hasReference: { id: tagId, type: 'tag' }, + }); + + return dashboardsResponse.savedObjects.map((item) => ({ + ...item, + title: item.attributes.title?.toString() ?? undefined, + description: item.attributes.description?.toString() ?? undefined, + })); + } + } + return []; +}; + +export const useSecurityDashboardsTableItems = () => { + const [dashboardItems, setDashboardItems] = useState([]); + + const { + savedObjects: { client: savedObjectsClient }, + } = useKibana().services; + + useEffect(() => { + let ignore = false; + const fetchDashboards = async () => { + const items = await getSecurityDashboardItems(savedObjectsClient); + if (!ignore) { + setDashboardItems(items); + } + }; + + fetchDashboards(); + return () => { + ignore = true; + }; + }, [savedObjectsClient]); + + return dashboardItems; +}; + +export const useDashboardsTableColumns = (): Array> => { + const { savedObjectsTagging, dashboard: { locator } = {} } = useKibana().services; + const { navigateTo } = useNavigateTo(); + + const getNavigationHandler = useCallback( + (href: string): MouseEventHandler => + (ev) => { + ev.preventDefault(); + navigateTo({ url: href }); + }, + [navigateTo] + ); + + const columns = useMemo( + (): Array> => [ + { + field: 'title', + name: i18n.DASHBOARD_TITLE, + 'data-test-subj': 'dashboard-title-field', + render: (title: string, { id }) => { + const href = locator?.getRedirectUrl({ dashboardId: id }); + return href ? ( + + {title} + + ) : ( + title + ); + }, + }, + { + field: 'description', + name: i18n.DASHBOARDS_DESCRIPTION, + 'data-test-subj': 'dashboard-description-field', + render: (description: string) => description || EMPTY_DESCRIPTION, + }, + // adds the tags table column based on the saved object items + ...(savedObjectsTagging ? [savedObjectsTagging.ui.getTableColumnDefinition()] : []), + ], + [getNavigationHandler, locator, savedObjectsTagging] + ); + + return columns; +}; diff --git a/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_search_bar_url_params.ts b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_search_bar_url_params.ts index 0424b86619bb2..608f38b7428a9 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_search_bar_url_params.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_search_bar_url_params.ts @@ -14,7 +14,7 @@ import { inputsActions } from '../../store/inputs'; import { useInitializeUrlParam } from '../../utils/global_query_string'; import { CONSTANTS } from '../../components/url_state/constants'; -export const useInitSearchBarUrlParams = () => { +export const useInitSearchBarFromUrlParams = () => { const dispatch = useDispatch(); const { filterManager, savedQueries } = useKibana().services.data.query; const getGlobalFiltersQuerySelector = useMemo( @@ -23,7 +23,7 @@ export const useInitSearchBarUrlParams = () => { ); const filtersFromStore = useSelector(getGlobalFiltersQuerySelector); - const onInitializeAppQueryUrlParam = useCallback( + const onInitializeAppQueryFromUrlParam = useCallback( (initialState: Query | null) => { if (initialState != null) { dispatch( @@ -38,7 +38,7 @@ export const useInitSearchBarUrlParams = () => { [dispatch] ); - const onInitializeFiltersUrlParam = useCallback( + const onInitializeFiltersFromUrlParam = useCallback( (initialState: Filter[] | null) => { if (initialState != null) { filterManager.setFilters(initialState); @@ -63,7 +63,7 @@ export const useInitSearchBarUrlParams = () => { [filterManager, dispatch, filtersFromStore] ); - const onInitializeSavedQueryUrlParam = useCallback( + const onInitializeSavedQueryFromUrlParam = useCallback( (savedQueryId: string | null) => { if (savedQueryId != null && savedQueryId !== '') { savedQueries.getSavedQuery(savedQueryId).then((savedQueryData) => { @@ -91,7 +91,7 @@ export const useInitSearchBarUrlParams = () => { [dispatch, filterManager, savedQueries] ); - useInitializeUrlParam(CONSTANTS.appQuery, onInitializeAppQueryUrlParam); - useInitializeUrlParam(CONSTANTS.filters, onInitializeFiltersUrlParam); - useInitializeUrlParam(CONSTANTS.savedQuery, onInitializeSavedQueryUrlParam); + useInitializeUrlParam(CONSTANTS.appQuery, onInitializeAppQueryFromUrlParam); + useInitializeUrlParam(CONSTANTS.filters, onInitializeFiltersFromUrlParam); + useInitializeUrlParam(CONSTANTS.savedQuery, onInitializeSavedQueryFromUrlParam); }; diff --git a/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_timerange_url_params.ts b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_timerange_url_params.ts new file mode 100644 index 0000000000000..2d5c00aa600f5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_timerange_url_params.ts @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useCallback } from 'react'; +import { get, isEmpty } from 'lodash/fp'; +import { useDispatch } from 'react-redux'; +import type { Dispatch } from 'redux'; +import type { InputsModelId, TimeRangeKinds } from '../../store/inputs/constants'; +import type { + AbsoluteTimeRange, + LinkTo, + RelativeTimeRange, + UrlInputsModel, +} from '../../store/inputs/model'; +import { normalizeTimeRange } from '../../components/url_state/normalize_time_range'; +import { inputsActions } from '../../store/inputs'; +import { formatDate } from '../../components/super_date_picker'; +import { useInitializeUrlParam } from '../../utils/global_query_string'; +import { CONSTANTS } from '../../components/url_state/constants'; + +export const useInitTimerangeFromUrlParam = () => { + const dispatch = useDispatch(); + + const onInitialize = useCallback( + (initialState: UrlInputsModel | null) => + initializeTimerangeFromUrlParam(initialState, dispatch), + [dispatch] + ); + + useInitializeUrlParam(CONSTANTS.timerange, onInitialize); +}; + +const initializeTimerangeFromUrlParam = ( + initialState: UrlInputsModel | null, + dispatch: Dispatch +) => { + if (initialState != null) { + const globalId: InputsModelId = 'global'; + const globalLinkTo: LinkTo = { linkTo: get('global.linkTo', initialState) }; + const globalType: TimeRangeKinds = get('global.timerange.kind', initialState); + + const timelineId: InputsModelId = 'timeline'; + const timelineLinkTo: LinkTo = { linkTo: get('timeline.linkTo', initialState) }; + const timelineType: TimeRangeKinds = get('timeline.timerange.kind', initialState); + + if (isEmpty(globalLinkTo.linkTo)) { + dispatch(inputsActions.removeGlobalLinkTo()); + } else { + dispatch(inputsActions.addGlobalLinkTo({ linkToId: 'timeline' })); + } + + if (isEmpty(timelineLinkTo.linkTo)) { + dispatch(inputsActions.removeTimelineLinkTo()); + } else { + dispatch(inputsActions.addTimelineLinkTo({ linkToId: 'global' })); + } + + if (timelineType) { + if (timelineType === 'absolute') { + const absoluteRange = normalizeTimeRange( + get('timeline.timerange', initialState) + ); + + dispatch( + inputsActions.setAbsoluteRangeDatePicker({ + ...absoluteRange, + id: timelineId, + }) + ); + } + + if (timelineType === 'relative') { + const relativeRange = normalizeTimeRange( + get('timeline.timerange', initialState) + ); + + // Updates date values when timerange is relative + relativeRange.from = formatDate(relativeRange.fromStr); + relativeRange.to = formatDate(relativeRange.toStr, { + roundUp: true, + }); + + dispatch( + inputsActions.setRelativeRangeDatePicker({ + ...relativeRange, + id: timelineId, + }) + ); + } + } + + if (globalType) { + if (globalType === 'absolute') { + const absoluteRange = normalizeTimeRange( + get('global.timerange', initialState) + ); + + dispatch( + inputsActions.setAbsoluteRangeDatePicker({ + ...absoluteRange, + id: globalId, + }) + ); + } + if (globalType === 'relative') { + const relativeRange = normalizeTimeRange( + get('global.timerange', initialState) + ); + + // Updates date values when timerange is relative + relativeRange.from = formatDate(relativeRange.fromStr); + relativeRange.to = formatDate(relativeRange.toStr, { + roundUp: true, + }); + + dispatch( + inputsActions.setRelativeRangeDatePicker({ + ...relativeRange, + id: globalId, + }) + ); + } + } + } +}; diff --git a/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_sync_timerange_url_param.ts b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_sync_timerange_url_param.ts new file mode 100644 index 0000000000000..a14299b7f2267 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_sync_timerange_url_param.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { useEffect, useMemo } from 'react'; +import { useSelector } from 'react-redux'; +import type { UrlInputsModel } from '../../store/inputs/model'; +import { inputsSelectors } from '../../store/inputs'; +import { useUpdateUrlParam } from '../../utils/global_query_string'; +import { CONSTANTS } from '../../components/url_state/constants'; + +export const useSyncTimerangeUrlParam = () => { + const updateTimerangeUrlParam = useUpdateUrlParam(CONSTANTS.timerange); + const getInputSelector = useMemo(() => inputsSelectors.inputsSelector(), []); + const inputState = useSelector(getInputSelector); + + const { linkTo: globalLinkTo, timerange: globalTimerange } = inputState.global; + const { linkTo: timelineLinkTo, timerange: timelineTimerange } = inputState.timeline; + + useEffect(() => { + updateTimerangeUrlParam({ + global: { + [CONSTANTS.timerange]: globalTimerange, + linkTo: globalLinkTo, + }, + timeline: { + [CONSTANTS.timerange]: timelineTimerange, + linkTo: timelineLinkTo, + }, + }); + }, [updateTimerangeUrlParam, globalLinkTo, globalTimerange, timelineLinkTo, timelineTimerange]); +}; diff --git a/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_update_timerange_on_page_change.ts b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_update_timerange_on_page_change.ts new file mode 100644 index 0000000000000..79fdc5ddd2c12 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_update_timerange_on_page_change.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEffect, useMemo } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import usePrevious from 'react-use/lib/usePrevious'; +import type { SecurityPageName } from '../../../app/types'; +import { formatDate } from '../../components/super_date_picker'; +import { isDetectionsPages } from '../../components/url_state/helpers'; +import { inputsSelectors } from '../../store'; +import { inputsActions } from '../../store/inputs'; +import type { InputsModelId } from '../../store/inputs/constants'; +import { useRouteSpy } from '../../utils/route/use_route_spy'; + +const globalId: InputsModelId = 'global'; +const timelineId: InputsModelId = 'timeline'; + +/** + * Update relative time ranges when navigating between pages. + * + * Ex: When 'toStr' is 'now' and we navigate to a new page, it updates `to` with the present date-time. + * + * * It does not update the time range on the landing page. + * * It only updates the time range when navigating to detection pages for performance reasons. + */ +export const useUpdateTimerangeOnPageChange = () => { + const [{ pageName }] = useRouteSpy(); + const dispatch = useDispatch(); + const previousPage = usePrevious(pageName); + const getInputSelector = useMemo(() => inputsSelectors.inputsSelector(), []); + const inputState = useSelector(getInputSelector); + + const { timerange: globalTimerange } = inputState.global; + const { timerange: timelineTimerange } = inputState.timeline; + + useEffect(() => { + if (isNavigatingToDetections(pageName, previousPage)) { + if (timelineTimerange.kind === 'relative') { + dispatch( + inputsActions.setRelativeRangeDatePicker({ + ...timelineTimerange, + from: formatDate(timelineTimerange.fromStr), + to: formatDate(timelineTimerange.toStr, { + roundUp: true, + }), + id: timelineId, + }) + ); + } + + if (globalTimerange.kind === 'relative') { + dispatch( + inputsActions.setRelativeRangeDatePicker({ + ...globalTimerange, + from: formatDate(globalTimerange.fromStr), + to: formatDate(globalTimerange.toStr, { + roundUp: true, + }), + + id: globalId, + }) + ); + } + } + }, [pageName, previousPage, dispatch, timelineTimerange, globalTimerange]); +}; + +const isNavigatingToDetections = ( + pageName: SecurityPageName | undefined, + previousPage: SecurityPageName | undefined +) => pageName && previousPage && previousPage !== pageName && isDetectionsPages(pageName); diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_url_state.ts b/x-pack/plugins/security_solution/public/common/hooks/use_url_state.ts new file mode 100644 index 0000000000000..f9e964fff54ed --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/use_url_state.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useSyncGlobalQueryString } from '../utils/global_query_string'; +import { useInitSearchBarFromUrlParams } from './search_bar/use_init_search_bar_url_params'; +import { useInitTimerangeFromUrlParam } from './search_bar/use_init_timerange_url_params'; +import { useUpdateTimerangeOnPageChange } from './search_bar/use_update_timerange_on_page_change'; + +export const useUrlState = () => { + useSyncGlobalQueryString(); + useInitSearchBarFromUrlParams(); + useInitTimerangeFromUrlParam(); + useUpdateTimerangeOnPageChange(); +}; diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts index 11fdb39b5315a..ae3e7bdcef3f7 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/__mocks__/index.ts @@ -53,6 +53,11 @@ export const useKibana = jest.fn().mockReturnValue({ }, }, timelines: createTGridMocks(), + savedObjectsTagging: { + ui: { + getTableColumnDefinition: jest.fn(), + }, + }, }, }); export const useUiSetting = jest.fn(createUseUiSettingMock()); diff --git a/x-pack/plugins/security_solution/public/kubernetes/pages/translations.ts b/x-pack/plugins/security_solution/public/kubernetes/pages/translations.ts index 1b2c308c0bfa6..9b1024494f4f0 100644 --- a/x-pack/plugins/security_solution/public/kubernetes/pages/translations.ts +++ b/x-pack/plugins/security_solution/public/kubernetes/pages/translations.ts @@ -28,7 +28,7 @@ export const COLUMN_NODE = i18n.translate('xpack.securitySolution.kubernetes.col export const COLUMN_ENTRY_USER = i18n.translate( 'xpack.securitySolution.kubernetes.columnEntryUser', { - defaultMessage: 'Session entry users', + defaultMessage: 'Session entry user', } ); @@ -42,7 +42,7 @@ export const COLUMN_INTERACTIVE = i18n.translate( export const COLUMN_ENTRY_TYPE = i18n.translate( 'xpack.securitySolution.kubernetes.columnEntryType', { - defaultMessage: 'Entry mechanism', + defaultMessage: 'Entry type', } ); diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx index 377c7efe0e3fe..b14e62f222576 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { SecurityPageName } from '../../app/types'; import type { NavLinkItem } from '../../common/components/navigation/types'; import { TestProviders } from '../../common/mock'; -import { LandingLinksImages } from './landing_links_images'; +import { LandingLinksImages, LandingImageCards } from './landing_links_images'; const DEFAULT_NAV_ITEM: NavLinkItem = { id: SecurityPageName.overview, @@ -57,3 +57,30 @@ describe('LandingLinksImages', () => { expect(getByTestId('LandingLinksImage')).toHaveAttribute('src', image); }); }); + +describe('LandingImageCards', () => { + it('renders', () => { + const title = 'test label'; + + const { queryByText } = render( + + + + ); + + expect(queryByText(title)).toBeInTheDocument(); + }); + + it('renders image', () => { + const image = 'test_image.jpeg'; + const title = 'TEST_LABEL'; + + const { getByTestId } = render( + + + + ); + + expect(getByTestId('LandingImageCard-image')).toHaveAttribute('src', image); + }); +}); diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx index 9a6787083f848..5f54d4c53693f 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx @@ -4,13 +4,21 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiImage, EuiPanel, EuiText, EuiTitle } from '@elastic/eui'; +import { + EuiCard, + EuiFlexGroup, + EuiFlexItem, + EuiImage, + EuiPanel, + EuiText, + EuiTitle, +} from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; import { withSecuritySolutionLink } from '../../common/components/links'; import type { NavLinkItem } from '../../common/components/navigation/types'; -interface LandingLinksImagesProps { +interface LandingImagesProps { items: NavLinkItem[]; } @@ -31,13 +39,13 @@ const StyledFlexItem = styled(EuiFlexItem)` align-items: center; `; -const SecuritySolutionLink = withSecuritySolutionLink(Link); - const Content = styled(EuiFlexItem)` padding-left: ${({ theme }) => theme.eui.euiSizeS}; `; -export const LandingLinksImages: React.FC = ({ items }) => ( +const SecuritySolutionLink = withSecuritySolutionLink(Link); + +export const LandingLinksImages: React.FC = ({ items }) => ( {items.map(({ title, description, image, id }) => ( @@ -71,3 +79,58 @@ export const LandingLinksImages: React.FC = ({ items }) ))} ); + +const LandingImageCardItem = styled(EuiFlexItem)` + max-width: 364px; +`; + +const LandingCardDescripton = styled(EuiText)` + padding-top: ${({ theme }) => theme.eui.euiSizeXS}; +`; + +// Needed to use the primary color in the title underlining on hover +const PrimaryTitleCard = styled(EuiCard)` + .euiCard__title { + color: ${(props) => props.theme.eui.euiColorPrimary}; + } +`; + +const SecuritySolutionCard = withSecuritySolutionLink(PrimaryTitleCard); + +export const LandingImageCards: React.FC = React.memo(({ items }) => ( + + {items.map(({ id, image, title, description }) => ( + + + ) + } + title={ + +

    {title}

    +
    + } + description={ + + {description} + + } + /> +
    + ))} +
    +)); + +LandingImageCards.displayName = 'LandingImageCards'; diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.test.tsx b/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.test.tsx new file mode 100644 index 0000000000000..81f2c59e9bd85 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.test.tsx @@ -0,0 +1,128 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { fireEvent, render } from '@testing-library/react'; +import React from 'react'; +import { SecurityPageName } from '../../app/types'; +import { TestProviders } from '../../common/mock'; +import { DashboardsLandingPage } from './dashboards'; +import type { NavLinkItem } from '../../common/components/navigation/types'; + +jest.mock('../../common/utils/route/spy_routes', () => ({ SpyRoute: () => null })); + +const OVERVIEW_ITEM_LABEL = 'Overview'; +const DETECTION_RESPONSE_ITEM_LABEL = 'Detection & Response'; + +const defaultAppDashboardsLink: NavLinkItem = { + id: SecurityPageName.dashboardsLanding, + title: 'Dashboards', + links: [ + { + id: SecurityPageName.overview, + title: OVERVIEW_ITEM_LABEL, + description: '', + icon: 'testIcon1', + }, + { + id: SecurityPageName.detectionAndResponse, + title: DETECTION_RESPONSE_ITEM_LABEL, + description: '', + icon: 'testIcon2', + }, + ], +}; + +const mockAppManageLink = jest.fn(() => defaultAppDashboardsLink); +jest.mock('../../common/components/navigation/nav_links', () => ({ + useAppRootNavLink: () => mockAppManageLink(), +})); + +const dashboardTableItems = [ + { + id: 'id 1', + title: 'dashboard title 1', + description: 'dashboard desc 1', + }, + { + id: 'id 2', + title: 'dashboard title 2', + description: 'dashboard desc 2', + }, +]; +const mockUseSecurityDashboardsTableItems = jest.fn(() => dashboardTableItems); +jest.mock('../../common/containers/dashboards/use_security_dashboards', () => { + const actual = jest.requireActual('../../common/containers/dashboards/use_security_dashboards'); + return { + ...actual, + useSecurityDashboardsTableItems: () => mockUseSecurityDashboardsTableItems(), + }; +}); + +const renderDashboardLanding = () => render(, { wrapper: TestProviders }); + +describe('Dashboards landing', () => { + it('should render items', () => { + const { queryByText } = renderDashboardLanding(); + + expect(queryByText(OVERVIEW_ITEM_LABEL)).toBeInTheDocument(); + expect(queryByText(DETECTION_RESPONSE_ITEM_LABEL)).toBeInTheDocument(); + }); + + it('should render items in the same order as defined', () => { + mockAppManageLink.mockReturnValueOnce({ + ...defaultAppDashboardsLink, + }); + const { queryAllByTestId } = renderDashboardLanding(); + + const renderedItems = queryAllByTestId('LandingImageCard-item'); + + expect(renderedItems[0]).toHaveTextContent(OVERVIEW_ITEM_LABEL); + expect(renderedItems[1]).toHaveTextContent(DETECTION_RESPONSE_ITEM_LABEL); + }); + + it('should not render items if all items filtered', () => { + mockAppManageLink.mockReturnValueOnce({ + ...defaultAppDashboardsLink, + links: [], + }); + const { queryByText } = renderDashboardLanding(); + + expect(queryByText(OVERVIEW_ITEM_LABEL)).not.toBeInTheDocument(); + expect(queryByText(DETECTION_RESPONSE_ITEM_LABEL)).not.toBeInTheDocument(); + }); + + it('should render dashboards table', () => { + const result = renderDashboardLanding(); + + expect(result.getByTestId('dashboards-table')).toBeInTheDocument(); + }); + + it('should render dashboards table rows', () => { + const result = renderDashboardLanding(); + + expect(mockUseSecurityDashboardsTableItems).toHaveBeenCalled(); + + expect(result.queryAllByText(dashboardTableItems[0].title).length).toBeGreaterThan(0); + expect(result.queryAllByText(dashboardTableItems[0].description).length).toBeGreaterThan(0); + + expect(result.queryAllByText(dashboardTableItems[1].title).length).toBeGreaterThan(0); + expect(result.queryAllByText(dashboardTableItems[1].description).length).toBeGreaterThan(0); + }); + + it('should render dashboards table rows filtered by search term', () => { + const result = renderDashboardLanding(); + + const input = result.getByRole('searchbox'); + fireEvent.change(input, { target: { value: dashboardTableItems[0].title } }); + + expect(result.queryAllByText(dashboardTableItems[0].title).length).toBeGreaterThan(0); + expect(result.queryAllByText(dashboardTableItems[0].description).length).toBeGreaterThan(0); + + expect(result.queryByText(dashboardTableItems[1].title)).not.toBeInTheDocument(); + expect(result.queryByText(dashboardTableItems[1].description)).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.tsx b/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.tsx index 1d46aa6706a26..15afdedb4dd93 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/dashboards.tsx @@ -4,22 +4,39 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { EuiHorizontalRule, EuiSpacer, EuiTitle } from '@elastic/eui'; import React from 'react'; import { SecurityPageName } from '../../app/types'; +import { DashboardsTable } from '../../common/components/dashboards/dashboards_table'; import { HeaderPage } from '../../common/components/header_page'; import { useAppRootNavLink } from '../../common/components/navigation/nav_links'; import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; import { SpyRoute } from '../../common/utils/route/spy_routes'; -import { LandingLinksImages } from '../components/landing_links_images'; -import { DASHBOARDS_PAGE_TITLE } from './translations'; +import { LandingImageCards } from '../components/landing_links_images'; +import * as i18n from './translations'; export const DashboardsLandingPage = () => { const dashboardLinks = useAppRootNavLink(SecurityPageName.dashboardsLanding)?.links ?? []; return ( - - + + + + +

    {i18n.DASHBOARDS_PAGE_SECTION_DEFAULT}

    +
    + + + + + +

    {i18n.DASHBOARDS_PAGE_SECTION_CUSTOM}

    +
    + + + +
    ); diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/translations.ts b/x-pack/plugins/security_solution/public/landing_pages/pages/translations.ts index 4986c6b5f31ec..9b8b8f71ce509 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/pages/translations.ts +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/translations.ts @@ -21,6 +21,20 @@ export const DASHBOARDS_PAGE_TITLE = i18n.translate( } ); +export const DASHBOARDS_PAGE_SECTION_DEFAULT = i18n.translate( + 'xpack.securitySolution.landing.dashboards.section.default', + { + defaultMessage: 'DEFAULT', + } +); + +export const DASHBOARDS_PAGE_SECTION_CUSTOM = i18n.translate( + 'xpack.securitySolution.landing.dashboards.section.custom', + { + defaultMessage: 'CUSTOM', + } +); + export const MANAGE_PAGE_TITLE = i18n.translate('xpack.securitySolution.landing.manage.pageTitle', { defaultMessage: 'Manage', }); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx index 42990db6e48ce..2701ebdb136b5 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx @@ -10,7 +10,7 @@ import type { ConsoleTestSetup } from '../../mocks'; import { getConsoleTestSetup } from '../../mocks'; import type { ConsoleProps } from '../../types'; import { INPUT_DEFAULT_PLACEHOLDER_TEXT } from '../console_state/state_update_handlers/handle_input_area_state'; -import { waitFor } from '@testing-library/react'; +import { act, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; describe('When entering data into the Console input', () => { @@ -92,14 +92,40 @@ describe('When entering data into the Console input', () => { expect(getFooterText()).toEqual('Unknown command abc'); }); - it('should display the input history popover when UP key is pressed', async () => { + it('should show the arrow button as not disabled if input has text entered', () => { + render(); + enterCommand('cm ', { inputOnly: true }); + + const arrowButton = renderResult.getByTestId('test-inputTextSubmitButton'); + expect(arrowButton).not.toBeDisabled(); + }); + + it('should show the arrow button as disabled if input area is blank', () => { + render(); + + const arrowButton = renderResult.getByTestId('test-inputTextSubmitButton'); + expect(arrowButton).toBeDisabled(); + }); + + it('should execute correct command if arrow button is clicked', () => { + render(); + enterCommand('isolate', { inputOnly: true }); + act(() => { + renderResult.getByTestId('test-inputTextSubmitButton').click(); + }); + expect(renderResult.getByTestId('test-userCommandText').textContent).toEqual('isolate'); + }); + + // FIXME:PT uncomment once task OLM task #4384 is implemented + it.skip('should display the input history popover when UP key is pressed', async () => { render(); await showInputHistoryPopover(); expect(renderResult.getByTestId('test-inputHistorySelector')).not.toBeNull(); }); - describe('and when the command input history popover is opened', () => { + // FIXME:PT uncomment once task OLM task #4384 is implemented + describe.skip('and when the command input history popover is opened', () => { const renderWithInputHistory = async (inputText: string = '') => { render(); enterCommand('help'); @@ -237,7 +263,8 @@ describe('When entering data into the Console input', () => { expect(getFooterText()).toEqual('cmd1 '); }); - it('should return original cursor position if input history is closed with no selection', async () => { + // FIXME:PT uncomment once task OLM task #4384 is implemented + it.skip('should return original cursor position if input history is closed with no selection', async () => { typeKeyboardKey('{Enter}'); // add `isolate` to the input history typeKeyboardKey('release'); @@ -262,7 +289,8 @@ describe('When entering data into the Console input', () => { expect(getRightOfCursorText()).toEqual('elease'); }); - it('should reset cursor position to default (at end) if a selection is done from input history', async () => { + // FIXME:PT uncomment once task OLM task #4384 is implemented + it.skip('should reset cursor position to default (at end) if a selection is done from input history', async () => { typeKeyboardKey('{Enter}'); // add `isolate` to the input history typeKeyboardKey('release'); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.tsx index 9c5d528c46659..a4ff5b03b45e8 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.tsx @@ -8,7 +8,7 @@ import type { MouseEventHandler } from 'react'; import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import type { CommonProps } from '@elastic/eui'; -import { EuiFlexGroup, EuiFlexItem, useResizeObserver } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, useResizeObserver, EuiButtonIcon } from '@elastic/eui'; import styled from 'styled-components'; import classNames from 'classnames'; import type { ConsoleDataState } from '../console_state/types'; @@ -110,6 +110,25 @@ export const CommandInput = memo(({ prompt = '', focusRef, .. }); }, [isKeyInputBeingCaptured]); + const disableArrowButton = useMemo( + () => textEntered.length === 0 && rightOfCursor.text.length === 0, + [rightOfCursor.text.length, textEntered.length] + ); + + const handleSubmitButton = useCallback( + (ev) => { + setCommandToExecute(textEntered + rightOfCursor.text); + dispatch({ + type: 'updateInputTextEnteredState', + payload: { + textEntered: '', + rightOfCursor: undefined, + }, + }); + }, + [dispatch, textEntered, rightOfCursor.text] + ); + const handleKeyCaptureOnStateChange = useCallback>( (isCapturing) => { setIsKeyInputBeingCaptured(isCapturing); @@ -131,12 +150,13 @@ export const CommandInput = memo(({ prompt = '', focusRef, .. const keyCode = eventDetails.keyCode; // UP arrow key - if (keyCode === 38) { - dispatch({ type: 'removeFocusFromKeyCapture' }); - dispatch({ type: 'updateInputPopoverState', payload: { show: 'input-history' } }); - - return; - } + // FIXME:PT to be addressed via OLM task #4384 + // if (keyCode === 38) { + // dispatch({ type: 'removeFocusFromKeyCapture' }); + // dispatch({ type: 'updateInputPopoverState', payload: { show: 'input-history' } }); + // + // return; + // } // Update the store with the updated text that was entered dispatch({ @@ -284,6 +304,17 @@ export const CommandInput = memo(({ prompt = '', focusRef, ..
    + + + eui.euiSizeS}; + .euiTableHeaderCell { + .euiTableCellContent__text { + color: ${({ theme: { eui } }) => eui.euiTextColor}; + font-size: ${({ theme: { eui } }) => eui.euiFontSize}; + padding-bottom: ${({ theme: { eui } }) => eui.euiSizeS}; + padding-left: ${({ theme: { eui } }) => eui.euiSizeS}; + } + } +`; + +const StyledEuiCallOut = styled(EuiCallOut)` + margin: ${({ theme: { eui } }) => eui.euiSize}; + border-radius: ${({ theme: { eui } }) => eui.euiSizeXS}; +`; + +const StyledEuiFlexGroup = styled(EuiFlexGroup)` + padding-left: ${({ theme: { eui } }) => eui.euiSizeS}; +`; export interface CommandListProps { commands: CommandDefinition[]; + display?: 'default' | 'table'; } -export const CommandList = memo(({ commands }) => { +export const CommandList = memo(({ commands, display = 'default' }) => { const getTestId = useTestIdGenerator(useDataTestSubj()); + const dispatch = useConsoleStateDispatch(); const footerMessage = useMemo(() => { return ( @@ -41,26 +76,207 @@ export const CommandList = memo(({ commands }) => { ); }, []); + const otherCommandsGroupLabel = i18n.translate( + 'xpack.securitySolution.console.commandList.otherCommandsGroup.label', + { + defaultMessage: 'Other commands', + } + ); + + const updateInputText = useCallback( + (text) => () => { + dispatch({ + type: 'updateInputTextEnteredState', + payload: () => { + return { + textEntered: text, + }; + }, + }); + }, + [dispatch] + ); + + const commandsByGroups = useMemo(() => { + return Object.values(groupBy(commands, 'helpGroupLabel')).reduce( + (acc, current) => { + if (current[0].helpGroupPosition !== undefined) { + // If it already exists just move it to the end + if (acc[current[0].helpGroupPosition]) { + acc[acc.length] = acc[current[0].helpGroupPosition]; + } + + acc[current[0].helpGroupPosition] = sortBy(current, 'helpCommandPosition'); + } else if (current.length) { + acc.push(current); + } + return acc; + }, + [] + ); + }, [commands]); + + const getTableItems = useCallback( + ( + commandsByGroup: CommandDefinition[] + ): Array<{ + [key: string]: { name: string; about: React.ElementType | string }; + }> => { + if (commandsByGroup[0].helpGroupLabel === HELP_GROUPS.supporting.label) { + return [...COMMON_ARGS, ...commandsByGroup].map((command) => ({ + [commandsByGroup[0]?.helpGroupLabel ?? otherCommandsGroupLabel]: command, + })); + } + return commandsByGroup.map((command) => ({ + [commandsByGroup[0]?.helpGroupLabel ?? otherCommandsGroupLabel]: command, + })); + }, + [otherCommandsGroupLabel] + ); + + const getTableColumns = useCallback( + (commandsByGroup) => { + return [ + { + field: commandsByGroup[0]?.helpGroupLabel ?? otherCommandsGroupLabel, + name: commandsByGroup[0]?.helpGroupLabel ?? otherCommandsGroupLabel, + render: (command: CommandDefinition) => { + const commandNameWithArgs = getCommandNameWithArgs(command); + return ( + + + {commandNameWithArgs}, + description: ( + <> + + + {command.about} + + + ), + }, + ]} + data-test-subj={getTestId('commandList-command')} + /> + + {/* Show EuiButtonIcon if is a command */} + {command.RenderComponent && ( + + + + + + )} + + ); + }, + }, + ]; + }, + [getTestId, otherCommandsGroupLabel, updateInputText] + ); + + if (display === 'table') { + const calloutItems = [ + , + , + , + ]; + + const callout = ( + + } + > +
      + {calloutItems.map((item, index) => ( +
    1. + {item} +
    2. + ))} +
    + {/* //TODO: Add link to the read more page */} + + + +
    + ); + + return ( + <> + {commandsByGroups.map((commandsByGroup) => ( + + ))} + + {callout} + + ); + } + return ( <> - - {commands.map(({ name, about }) => { - return ( - - {name}, description: about }]} - data-test-subj={getTestId('commandList-command')} - /> - - ); - })} - - - - - {footerMessage} + {commandsByGroups.map((commandsByGroup) => { + const groupLabel = commandsByGroup[0].helpGroupLabel; + const groupedCommands = + groupLabel === HELP_GROUPS.supporting.label + ? [...commandsByGroup, ...COMMON_ARGS] + : commandsByGroup; + return ( + + {groupedCommands.map((command) => { + return ( + + {getCommandNameWithArgs(command)}, + description: <>{command.about}, + }, + ]} + data-test-subj={getTestId('commandList-command')} + /> + + ); + })} + + ); + })} + + + {footerMessage} ); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/console_header.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/console_header.tsx index 058486e13f0ab..b26b53fd7c2ac 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/console_header.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/console_header.tsx @@ -6,7 +6,8 @@ */ import React, { memo, useCallback } from 'react'; -import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { useConsoleStateDispatch } from '../hooks/state_selectors/use_console_state_dispatch'; import { useWithSidePanel } from '../hooks/state_selectors/use_with_side_panel'; @@ -40,17 +41,23 @@ export const ConsoleHeader = memo(({ TitleComponent }) => { {TitleComponent ? : ''} - - - + {!isHelpOpen && ( + + + + + + )} ); }); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/console_state/state_update_handlers/handle_execute_command.test.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/console_state/state_update_handlers/handle_execute_command.test.tsx index 2c7f30a83cd5c..2bb52f04109c9 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/console_state/state_update_handlers/handle_execute_command.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/console_state/state_update_handlers/handle_execute_command.test.tsx @@ -34,7 +34,8 @@ describe('When a Console command is entered by the user', () => { await waitFor(() => { expect(renderResult.getAllByTestId('test-commandList-command')).toHaveLength( // `+2` to account for builtin commands - commands.length + 2 + // `+2` to account for builtin generic args + commands.length + 4 ); }); }); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_content_layout.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_content_layout.tsx index fc086ce22be0e..82b9fdf5fb849 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_content_layout.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_content_layout.tsx @@ -8,12 +8,17 @@ import type { ReactNode } from 'react'; import React, { memo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; +import styled from 'styled-components'; export interface SidePanelContentLayoutProps { children: ReactNode; headerContent?: ReactNode; } +const StyledEuiFlexItemNoPadding = styled(EuiFlexItem)` + padding: 0 !important; +`; + /** * A layout component for displaying content in the right-side panel of the console */ @@ -34,9 +39,9 @@ export const SidePanelContentLayout = memo( )} - +
    {children}
    -
    + ); } diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_content_manager.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_content_manager.tsx index 376564ab896a7..7ba9cdedeea23 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_content_manager.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_content_manager.tsx @@ -6,37 +6,82 @@ */ import type { ReactNode } from 'react'; -import React, { memo, useMemo } from 'react'; -import { EuiText } from '@elastic/eui'; +import React, { memo, useMemo, useCallback } from 'react'; +import styled from 'styled-components'; +import { + EuiText, + EuiIcon, + EuiSpacer, + EuiFlexGroup, + EuiFlexItem, + EuiButtonIcon, + EuiTitle, +} from '@elastic/eui'; + import { FormattedMessage } from '@kbn/i18n-react'; import { CommandList } from '../command_list'; import { useWithCommandList } from '../../hooks/state_selectors/use_with_command_list'; import { SidePanelContentLayout } from './side_panel_content_layout'; import { useWithSidePanel } from '../../hooks/state_selectors/use_with_side_panel'; +import { useConsoleStateDispatch } from '../../hooks/state_selectors/use_console_state_dispatch'; + +const StyledEuiTitle = styled(EuiTitle)` + color: ${({ theme: { eui } }) => eui.euiTextSubduedColor}; +`; export const SidePanelContentManager = memo(() => { + const dispatch = useConsoleStateDispatch(); const commands = useWithCommandList(); const show = useWithSidePanel().show; + const closeHelpPanel = useCallback(() => { + dispatch({ + type: 'showSidePanel', + payload: { show: null }, + }); + }, [dispatch]); + const panelHeader: ReactNode = useMemo(() => { if (show === 'help') { return ( - - + <> + + + +

    + +

    +
    +
    + + + +
    + + }} /> -
    -
    +
    + ); } return null; - }, [show]); + }, [show, closeHelpPanel]); const panelBody: ReactNode = useMemo(() => { if (show === 'help') { - return ; + return ; } return null; diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_flex_item.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_flex_item.tsx index 20cca6401f633..f2c1cc2f3e192 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_flex_item.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/side_panel/side_panel_flex_item.tsx @@ -6,10 +6,18 @@ */ import React, { memo } from 'react'; -import { EuiFlexItem } from '@elastic/eui'; +import styled from 'styled-components'; +import { EuiFlexItem, transparentize } from '@elastic/eui'; import { SidePanelContentManager } from './side_panel_content_manager'; import { useWithSidePanel } from '../../hooks/state_selectors/use_with_side_panel'; +const StyledEuiFlexItemWhite = styled(EuiFlexItem)` + background-color: ${({ theme: { eui } }) => eui.euiHeaderBackgroundColor} !important; + border-radius: ${({ theme: { eui } }) => `0 ${eui.euiSizeXS} ${eui.euiSizeXS} 0`}; + box-shadow: 0 ${({ theme: { eui } }) => eui.euiSizeXS} ${({ theme: { eui } }) => eui.euiSizeXS} + ${({ theme: { eui } }) => transparentize(eui.euiShadowColor, 0.04)}; +`; + export const SidePanelFlexItem = memo((props) => { const isPanelOpened = Boolean(useWithSidePanel().show); @@ -18,9 +26,9 @@ export const SidePanelFlexItem = memo((props) => { } return ( - + - + ); }); SidePanelFlexItem.displayName = 'SidePanelFlexItem'; diff --git a/x-pack/plugins/security_solution/public/management/components/console/console.tsx b/x-pack/plugins/security_solution/public/management/components/console/console.tsx index e8fa86ffda83a..37850e888b126 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/console.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/console.tsx @@ -40,7 +40,7 @@ const ConsoleWindow = styled.div` &-container { padding: ${({ theme: { eui } }) => eui.euiSizeL} ${({ theme: { eui } }) => eui.euiSizeL} - ${({ theme: { eui } }) => eui.euiSizeS} ${({ theme: { eui } }) => eui.euiSizeL}; + ${({ theme: { eui } }) => eui.euiSizeS} ${({ theme: { eui } }) => eui.euiSizeM}; } &-header { @@ -139,46 +139,53 @@ export const Console = memo( dataTestSubj={commonProps['data-test-subj']} > - - - - + + + + + + - - - + - -
    + - -
    -
    - - - - - + +
    + +
    +
    + + + + + + +
    - - {}
    + {}
    diff --git a/x-pack/plugins/security_solution/public/management/components/console/service/builtin_commands.tsx b/x-pack/plugins/security_solution/public/management/components/console/service/builtin_commands.tsx index 485b43115e19b..4906143ff2c36 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/service/builtin_commands.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/service/builtin_commands.tsx @@ -10,6 +10,29 @@ import { ClearCommand } from '../components/builtin_commands/clear_command'; import { HelpCommand } from '../components/builtin_commands/help_command'; import type { CommandDefinition } from '../types'; +export const HELP_GROUPS = Object.freeze({ + supporting: { + label: i18n.translate('xpack.securitySolution.console.builtInCommands.groups.supporting', { + defaultMessage: 'Supporting commands & syntaxes', + }), + }, +}); + +export const COMMON_ARGS = Object.freeze([ + { + name: '--comment', + about: i18n.translate('xpack.securitySolution.console.commandList.commonArgs.comment', { + defaultMessage: 'Add comment to any action Ex: isolate --comment your comment', + }), + }, + { + name: '--help', + about: i18n.translate('xpack.securitySolution.console.commandList.commonArgs.help', { + defaultMessage: 'Command assistance Ex: isolate --help', + }), + }, +]); + export const getBuiltinCommands = (): CommandDefinition[] => { return [ { @@ -18,6 +41,7 @@ export const getBuiltinCommands = (): CommandDefinition[] => { defaultMessage: 'View list of available commands', }), RenderComponent: HelpCommand, + helpGroupLabel: HELP_GROUPS.supporting.label, }, { name: 'cls', @@ -25,6 +49,7 @@ export const getBuiltinCommands = (): CommandDefinition[] => { defaultMessage: 'Clear the console buffer', }), RenderComponent: ClearCommand, + helpGroupLabel: HELP_GROUPS.supporting.label, }, ]; }; diff --git a/x-pack/plugins/security_solution/public/management/components/console/service/utils.ts b/x-pack/plugins/security_solution/public/management/components/console/service/utils.ts new file mode 100644 index 0000000000000..faf7d12d12f80 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/console/service/utils.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { CommandArgs, CommandDefinition } from '../types'; + +export const getCommandNameWithArgs = (command: Partial) => { + if (!command.mustHaveArgs || !command.args) { + return command.name; + } + + let hasAnExclusiveOrArg = false; + const primaryArgs = Object.entries(command.args).reduce((acc, [key, value]) => { + if (value.required) { + acc[key] = value; + return acc; + } + if (value.exclusiveOr && !hasAnExclusiveOrArg) { + hasAnExclusiveOrArg = true; + acc[key] = value; + return acc; + } + return acc; + }, {}); + + return `${command.name} --${Object.keys(primaryArgs).join(' --')}`; +}; diff --git a/x-pack/plugins/security_solution/public/management/components/console/types.ts b/x-pack/plugins/security_solution/public/management/components/console/types.ts index dc3ff45f161e3..d929a8a4b4984 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/types.ts +++ b/x-pack/plugins/security_solution/public/management/components/console/types.ts @@ -35,11 +35,19 @@ export interface CommandArgs { export interface CommandDefinition { name: string; - about: string; + about: ComponentType | string; /** * The Component that will be used to render the Command */ RenderComponent: CommandExecutionComponent; + /** Will be used to sort the commands when building the output for the `help` command */ + helpCommandPosition?: number; + + /** A grouping label for the command */ + helpGroupLabel?: string; + + /** Used only when command help "grouping" is detected. Used to sort the groups of commands */ + helpGroupPosition?: number; /** * If defined, this command's use of `--help` will be displayed using this component instead of * the console's built in output. diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts index fec61d55c5e52..1a8476fb9c51c 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts @@ -23,6 +23,15 @@ const emptyArgumentValidator = (argData: ParsedArgData) => { } }; +const HELP_GROUPS = Object.freeze({ + responseActions: { + position: 0, + label: i18n.translate('xpack.securitySolution.endpointConsoleCommands.groups.responseActions', { + defaultMessage: 'Response actions', + }), + }, +}); + export const getEndpointResponseActionsConsoleCommands = ( endpointAgentId: string ): CommandDefinition[] => { @@ -48,6 +57,9 @@ export const getEndpointResponseActionsConsoleCommands = ( ), }, }, + helpGroupLabel: HELP_GROUPS.responseActions.label, + helpGroupPosition: HELP_GROUPS.responseActions.position, + helpCommandPosition: 0, }, { name: 'release', @@ -70,6 +82,9 @@ export const getEndpointResponseActionsConsoleCommands = ( ), }, }, + helpGroupLabel: HELP_GROUPS.responseActions.label, + helpGroupPosition: HELP_GROUPS.responseActions.position, + helpCommandPosition: 1, }, { name: 'kill-process', @@ -114,6 +129,9 @@ export const getEndpointResponseActionsConsoleCommands = ( validate: emptyArgumentValidator, }, }, + helpGroupLabel: HELP_GROUPS.responseActions.label, + helpGroupPosition: HELP_GROUPS.responseActions.position, + helpCommandPosition: 4, }, { name: 'suspend-process', @@ -161,6 +179,9 @@ export const getEndpointResponseActionsConsoleCommands = ( validate: emptyArgumentValidator, }, }, + helpGroupLabel: HELP_GROUPS.responseActions.label, + helpGroupPosition: HELP_GROUPS.responseActions.position, + helpCommandPosition: 5, }, { name: 'status', @@ -171,6 +192,9 @@ export const getEndpointResponseActionsConsoleCommands = ( meta: { endpointId: endpointAgentId, }, + helpGroupLabel: HELP_GROUPS.responseActions.label, + helpGroupPosition: HELP_GROUPS.responseActions.position, + helpCommandPosition: 2, }, { name: 'processes', @@ -193,6 +217,9 @@ export const getEndpointResponseActionsConsoleCommands = ( ), }, }, + helpGroupLabel: HELP_GROUPS.responseActions.label, + helpGroupPosition: HELP_GROUPS.responseActions.position, + helpCommandPosition: 3, }, ]; }; diff --git a/x-pack/plugins/security_solution/public/management/components/policy_response/policy_response_wrapper.test.tsx b/x-pack/plugins/security_solution/public/management/components/policy_response/policy_response_wrapper.test.tsx index dbd604d4c2c54..a4ef569c0a0c5 100644 --- a/x-pack/plugins/security_solution/public/management/components/policy_response/policy_response_wrapper.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/policy_response/policy_response_wrapper.test.tsx @@ -23,7 +23,8 @@ import { useGetEndpointDetails } from '../../hooks'; jest.mock('../../hooks/endpoint/use_get_endpoint_policy_response'); jest.mock('../../hooks/endpoint/use_get_endpoint_details'); -describe('when on the policy response', () => { +// FLAKY: https://github.com/elastic/kibana/issues/136272 +describe.skip('when on the policy response', () => { const docGenerator = new EndpointDocGenerator(); const createPolicyResponse = ( overallStatus: HostPolicyResponseActionStatus = HostPolicyResponseActionStatus.success, diff --git a/x-pack/plugins/security_solution/public/network/components/network_dns_table/mock.ts b/x-pack/plugins/security_solution/public/network/components/network_dns_table/mock.ts index 3fa4ddd3fc9c0..2af67776534b2 100644 --- a/x-pack/plugins/security_solution/public/network/components/network_dns_table/mock.ts +++ b/x-pack/plugins/security_solution/public/network/components/network_dns_table/mock.ts @@ -126,57 +126,5 @@ export const mockData: NetworkDnsStrategyResponse = { fakeTotalCount: 50, showMorePagesIndicator: true, }, - histogram: [ - { - x: 'nflxvideo.net', - g: 'nflxvideo.net', - y: 12546, - }, - { - x: 'apple.com', - g: 'apple.com', - y: 31687, - }, - { - x: 'googlevideo.com', - g: 'googlevideo.com', - y: 16292, - }, - { - x: 'netflix.com', - g: 'netflix.com', - y: 218193, - }, - { - x: 'samsungcloudsolution.com', - g: 'samsungcloudsolution.com', - y: 11702, - }, - { - x: 'doubleclick.net', - g: 'doubleclick.net', - y: 14372, - }, - { - x: 'digitalocean.com', - g: 'digitalocean.com', - y: 4111, - }, - { - x: 'samsungelectronics.com', - g: 'samsungelectronics.com', - y: 36592, - }, - { - x: 'google.com', - g: 'google.com', - y: 8072, - }, - { - x: 'samsungcloudsolution.net', - g: 'samsungcloudsolution.net', - y: 11518, - }, - ], rawResponse: {} as NetworkDnsStrategyResponse['rawResponse'], }; diff --git a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.test.tsx b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.test.tsx index af634f629fedd..34272cd7cbccf 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.test.tsx @@ -8,25 +8,73 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { TestProviders } from '../../../common/mock'; import { ID, useNetworkDns } from '.'; -import { NetworkType } from '../../store/model'; +import { useSearchStrategy } from '../../../common/containers/use_search_strategy'; + +jest.mock('../../../common/containers/use_search_strategy', () => ({ + useSearchStrategy: jest.fn(), +})); +const mockUseSearchStrategy = useSearchStrategy as jest.Mock; +const mockSearch = jest.fn(); + +const props = { + docValueFields: [], + endDate: '2020-07-08T08:20:18.966Z', + id: ID, + indexNames: ['auditbeat-*'], + skip: false, + startDate: '2020-07-07T08:20:18.966Z', +}; describe('useNetworkDns', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockUseSearchStrategy.mockReturnValue({ + loading: false, + result: { + edges: [], + totalCount: -1, + pageInfo: { + activePage: 0, + fakeTotalCount: 0, + showMorePagesIndicator: false, + }, + }, + search: mockSearch, + refetch: jest.fn(), + inspect: {}, + }); + }); + + it('runs search', () => { + renderHook(() => useNetworkDns(props), { + wrapper: TestProviders, + }); + + expect(mockSearch).toHaveBeenCalled(); + }); + + it('does not run search when skip = true', () => { + const localProps = { + ...props, + skip: true, + }; + renderHook(() => useNetworkDns(localProps), { + wrapper: TestProviders, + }); + + expect(mockSearch).not.toHaveBeenCalled(); + }); + it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); const localProps = { - docValueFields: [], - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - id: `${ID}-${NetworkType.page}`, - indexNames: ['cool'], - type: NetworkType.page, - skip: false, + ...props, }; const { rerender } = renderHook(() => useNetworkDns(localProps), { wrapper: TestProviders, }); localProps.skip = true; act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); + expect(mockUseSearchStrategy).toHaveBeenCalledTimes(3); + expect(mockUseSearchStrategy.mock.calls[2][0].abort).toEqual(true); }); }); diff --git a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx index e13036cc0d3bc..28dc7e657191c 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_dns/index.tsx @@ -5,37 +5,29 @@ * 2.0. */ -import { noop } from 'lodash/fp'; -import { useState, useEffect, useCallback, useMemo, useRef } from 'react'; +import { useState, useEffect, useCallback, useMemo } from 'react'; import deepEqual from 'fast-deep-equal'; -import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; import type { ESTermQuery } from '../../../../common/typed_json'; import type { inputsModel } from '../../../common/store'; import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; -import { useKibana } from '../../../common/lib/kibana'; import { createFilter } from '../../../common/containers/helpers'; import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers'; -import type { networkModel } from '../../store'; import { networkSelectors } from '../../store'; import type { DocValueFields, NetworkDnsRequestOptions, - NetworkDnsStrategyResponse, - MatrixOverOrdinalHistogramData, NetworkDnsEdges, PageInfoPaginated, } from '../../../../common/search_strategy'; import { NetworkQueries } from '../../../../common/search_strategy'; import * as i18n from './translations'; -import { getInspectResponse } from '../../../helpers'; import type { InspectResponse } from '../../../types'; -import { useAppToasts } from '../../../common/hooks/use_app_toasts'; +import { useSearchStrategy } from '../../../common/containers/use_search_strategy'; export const ID = 'networkDnsQuery'; -export interface NetworkDnsArgs { +export interface NetworkDnsResponse { id: string; inspect: InspectResponse; isInspected: boolean; @@ -45,14 +37,12 @@ export interface NetworkDnsArgs { refetch: inputsModel.Refetch; stackByField?: string; totalCount: number; - histogram: MatrixOverOrdinalHistogramData[]; } interface UseNetworkDns { id: string; docValueFields: DocValueFields[]; indexNames: string[]; - type: networkModel.NetworkType; filterQuery?: ESTermQuery | string; endDate: string; startDate: string; @@ -67,15 +57,9 @@ export const useNetworkDns = ({ indexNames, skip, startDate, - type, -}: UseNetworkDns): [boolean, NetworkDnsArgs] => { +}: UseNetworkDns): [boolean, NetworkDnsResponse] => { const getNetworkDnsSelector = useMemo(() => networkSelectors.dnsSelector(), []); const { activePage, sort, isPtrIncluded, limit } = useDeepEqualSelector(getNetworkDnsSelector); - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); const [networkDnsRequest, setNetworkDnsRequest] = useState(null); @@ -95,76 +79,39 @@ export const useNetworkDns = ({ [limit] ); - const [networkDnsResponse, setNetworkDnsResponse] = useState({ - networkDns: [], - histogram: [], - id, - inspect: { - dsl: [], - response: [], + const { + loading, + result: response, + search, + refetch, + inspect, + } = useSearchStrategy({ + factoryQueryType: NetworkQueries.dns, + initialResult: { + edges: [], + totalCount: -1, + pageInfo: { + activePage: 0, + fakeTotalCount: 0, + showMorePagesIndicator: false, + }, }, - isInspected: false, - loadPage: wrappedLoadMore, - pageInfo: { - activePage: 0, - fakeTotalCount: 0, - showMorePagesIndicator: false, - }, - refetch: refetch.current, - totalCount: -1, + errorMessage: i18n.ERROR_NETWORK_DNS, + abort: skip, }); - const { addError, addWarning } = useAppToasts(); - - const networkDnsSearch = useCallback( - (request: NetworkDnsRequestOptions | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - searchSubscription$.current = data.search - .search(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (isCompleteResponse(response)) { - setLoading(false); - setNetworkDnsResponse((prevResponse) => ({ - ...prevResponse, - networkDns: response.edges, - inspect: getInspectResponse(response, prevResponse.inspect), - pageInfo: response.pageInfo, - refetch: refetch.current, - totalCount: response.totalCount, - histogram: response.histogram ?? prevResponse.histogram, - })); - searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_NETWORK_DNS); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_NETWORK_DNS, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, addError, addWarning, skip] + const networkDnsResponse = useMemo( + () => ({ + id, + inspect, + isInspected: false, + loadPage: wrappedLoadMore, + networkDns: response.edges, + pageInfo: response.pageInfo, + refetch, + totalCount: response.totalCount, + }), + [id, inspect, refetch, response.edges, response.pageInfo, response.totalCount, wrappedLoadMore] ); useEffect(() => { @@ -202,20 +149,10 @@ export const useNetworkDns = ({ ]); useEffect(() => { - networkDnsSearch(networkDnsRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [networkDnsRequest, networkDnsSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); + if (!skip && networkDnsRequest) { + search(networkDnsRequest); } - }, [skip]); + }, [networkDnsRequest, search, skip]); return [loading, networkDnsResponse]; }; diff --git a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.test.tsx b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.test.tsx index 61ce547bce4ac..eef2087f51dad 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.test.tsx @@ -8,27 +8,76 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { TestProviders } from '../../../common/mock'; import { ID, useNetworkTopCountries } from '.'; -import { NetworkType } from '../../store/model'; +import { useSearchStrategy } from '../../../common/containers/use_search_strategy'; +import { networkModel } from '../../store'; import { FlowTargetSourceDest } from '../../../../common/search_strategy'; +jest.mock('../../../common/containers/use_search_strategy', () => ({ + useSearchStrategy: jest.fn(), +})); +const mockUseSearchStrategy = useSearchStrategy as jest.Mock; +const mockSearch = jest.fn(); + +const props = { + endDate: '2020-07-08T08:20:18.966Z', + flowTarget: FlowTargetSourceDest.source, + id: ID, + indexNames: ['auditbeat-*'], + skip: false, + startDate: '2020-07-07T08:20:18.966Z', + type: networkModel.NetworkType.page, +}; + describe('useNetworkTopCountries', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockUseSearchStrategy.mockReturnValue({ + loading: false, + result: { + edges: [], + totalCount: -1, + pageInfo: { + activePage: 0, + fakeTotalCount: 0, + showMorePagesIndicator: false, + }, + }, + search: mockSearch, + refetch: jest.fn(), + inspect: {}, + }); + }); + + it('runs search', () => { + renderHook(() => useNetworkTopCountries(props), { + wrapper: TestProviders, + }); + + expect(mockSearch).toHaveBeenCalled(); + }); + + it('does not run search when skip = true', () => { + const localProps = { + ...props, + skip: true, + }; + renderHook(() => useNetworkTopCountries(localProps), { + wrapper: TestProviders, + }); + + expect(mockSearch).not.toHaveBeenCalled(); + }); + it('skip = true will cancel any running request', () => { - const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); const localProps = { - docValueFields: [], - flowTarget: FlowTargetSourceDest.source, - startDate: '2020-07-07T08:20:18.966Z', - endDate: '2020-07-08T08:20:18.966Z', - id: `${ID}-${NetworkType.page}`, - indexNames: ['cool'], - type: NetworkType.page, - skip: false, + ...props, }; const { rerender } = renderHook(() => useNetworkTopCountries(localProps), { wrapper: TestProviders, }); localProps.skip = true; act(() => rerender()); - expect(abortSpy).toHaveBeenCalledTimes(4); + expect(mockUseSearchStrategy).toHaveBeenCalledTimes(3); + expect(mockUseSearchStrategy.mock.calls[2][0].abort).toEqual(true); }); }); diff --git a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx index 6631d3a9c2fcd..ab44e80043e3e 100644 --- a/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx +++ b/x-pack/plugins/security_solution/public/network/containers/network_top_countries/index.tsx @@ -5,16 +5,12 @@ * 2.0. */ -import { noop } from 'lodash/fp'; -import { useState, useEffect, useCallback, useMemo, useRef } from 'react'; +import { useState, useEffect, useCallback, useMemo } from 'react'; import deepEqual from 'fast-deep-equal'; -import { Subscription } from 'rxjs'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; import type { ESTermQuery } from '../../../../common/typed_json'; import type { inputsModel } from '../../../common/store'; import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; -import { useKibana } from '../../../common/lib/kibana'; import { createFilter } from '../../../common/containers/helpers'; import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers'; import type { networkModel } from '../../store'; @@ -23,14 +19,12 @@ import type { FlowTargetSourceDest, NetworkTopCountriesEdges, NetworkTopCountriesRequestOptions, - NetworkTopCountriesStrategyResponse, PageInfoPaginated, } from '../../../../common/search_strategy'; import { NetworkQueries } from '../../../../common/search_strategy'; -import { getInspectResponse } from '../../../helpers'; import type { InspectResponse } from '../../../types'; import * as i18n from './translations'; -import { useAppToasts } from '../../../common/hooks/use_app_toasts'; +import { useSearchStrategy } from '../../../common/containers/use_search_strategy'; export const ID = 'networkTopCountriesQuery'; @@ -72,18 +66,13 @@ export const useNetworkTopCountries = ({ const { activePage, limit, sort } = useDeepEqualSelector((state) => getTopCountriesSelector(state, type, flowTarget) ); - const { data } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [networkTopCountriesRequest, setHostRequest] = + const [networkTopCountriesRequest, setNetworkTopCountriesRequest] = useState(null); const wrappedLoadMore = useCallback( (newActivePage: number) => { - setHostRequest((prevRequest) => { + setNetworkTopCountriesRequest((prevRequest) => { if (!prevRequest) { return prevRequest; } @@ -96,80 +85,56 @@ export const useNetworkTopCountries = ({ }, [limit] ); - const { addError, addWarning } = useAppToasts(); - const [networkTopCountriesResponse, setNetworkTopCountriesResponse] = - useState({ - networkTopCountries: [], - id, - inspect: { - dsl: [], - response: [], - }, - isInspected: false, - loadPage: wrappedLoadMore, + const { + loading, + result: response, + search, + refetch, + inspect, + } = useSearchStrategy({ + factoryQueryType: NetworkQueries.topCountries, + initialResult: { + edges: [], + totalCount: -1, pageInfo: { activePage: 0, fakeTotalCount: 0, showMorePagesIndicator: false, }, - refetch: refetch.current, - totalCount: -1, - }); - - const networkTopCountriesSearch = useCallback( - (request: NetworkTopCountriesRequestOptions | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (isCompleteResponse(response)) { - setLoading(false); - setNetworkTopCountriesResponse((prevResponse) => ({ - ...prevResponse, - networkTopCountries: response.edges, - inspect: getInspectResponse(response, prevResponse.inspect), - pageInfo: response.pageInfo, - refetch: refetch.current, - totalCount: response.totalCount, - })); - searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - addWarning(i18n.ERROR_NETWORK_TOP_COUNTRIES); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - addError(msg, { - title: i18n.FAIL_NETWORK_TOP_COUNTRIES, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; }, - [data.search, addWarning, addError, skip] + errorMessage: i18n.FAIL_NETWORK_TOP_COUNTRIES, + abort: skip, + }); + + const networkTopCountriesResponse = useMemo( + () => ({ + endDate, + networkTopCountries: response.edges, + id, + inspect, + isInspected: false, + loadPage: wrappedLoadMore, + pageInfo: response.pageInfo, + refetch, + startDate, + totalCount: response.totalCount, + }), + [ + endDate, + id, + inspect, + refetch, + response.edges, + response.pageInfo, + response.totalCount, + startDate, + wrappedLoadMore, + ] ); useEffect(() => { - setHostRequest((prevRequest) => { + setNetworkTopCountriesRequest((prevRequest) => { const myRequest = { ...(prevRequest ?? {}), defaultIndex: indexNames, @@ -193,20 +158,10 @@ export const useNetworkTopCountries = ({ }, [activePage, indexNames, endDate, filterQuery, ip, limit, startDate, sort, flowTarget]); useEffect(() => { - networkTopCountriesSearch(networkTopCountriesRequest); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [networkTopCountriesRequest, networkTopCountriesSearch]); - - useEffect(() => { - if (skip) { - setLoading(false); - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); + if (!skip && networkTopCountriesRequest) { + search(networkTopCountriesRequest); } - }, [skip]); + }, [networkTopCountriesRequest, search, skip]); return [loading, networkTopCountriesResponse]; }; diff --git a/x-pack/plugins/security_solution/public/network/pages/navigation/dns_query_tab_body.tsx b/x-pack/plugins/security_solution/public/network/pages/navigation/dns_query_tab_body.tsx index 971c424d78fe1..ee423b0343088 100644 --- a/x-pack/plugins/security_solution/public/network/pages/navigation/dns_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/navigation/dns_query_tab_body.tsx @@ -89,7 +89,6 @@ const DnsQueryTabBodyComponent: React.FC = ({ indexNames, skip: querySkip, startDate, - type, }); const getTitle = useCallback( diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 986667363f7b6..39892dcd9b3ea 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -31,6 +31,7 @@ import type { AppObservableLibs, SubPlugins, StartedSubPlugins, + StartPluginsDependencies, } from './types'; import { initTelemetry } from './common/lib/telemetry'; import { KibanaServices } from './common/lib/kibana/services'; @@ -94,7 +95,10 @@ export class Plugin implements IPlugin, plugins: SetupPlugins): PluginSetup { + public setup( + core: CoreSetup, + plugins: SetupPlugins + ): PluginSetup { initTelemetry( { usageCollection: plugins.usageCollection, @@ -122,13 +126,16 @@ export class Plugin implements IPlugin = (async () => { - const [coreStart, startPlugins] = await core.getStartServices(); + const [coreStart, startPluginsDeps] = await core.getStartServices(); const { apm } = await import('@elastic/apm-rum'); + const { savedObjectsTaggingOss, ...startPlugins } = startPluginsDeps; + const services: StartServices = { ...coreStart, ...startPlugins, apm, + savedObjectsTagging: savedObjectsTaggingOss.getTaggingApi(), storage: this.storage, security: plugins.security, }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap index 1d8d5322c235b..063ebe2952cc0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/__snapshots__/field_renderers.test.tsx.snap @@ -146,7 +146,7 @@ exports[`Field Renderers #hostIdRenderer it renders correctly against snapshot 1 raspberrypi @@ -201,7 +201,7 @@ exports[`Field Renderers #hostNameRenderer it renders correctly against snapshot raspberrypi diff --git a/x-pack/plugins/security_solution/public/types.ts b/x-pack/plugins/security_solution/public/types.ts index 1a32eefa983e9..d1b6875635372 100644 --- a/x-pack/plugins/security_solution/public/types.ts +++ b/x-pack/plugins/security_solution/public/types.ts @@ -34,6 +34,10 @@ import type { DashboardStart } from '@kbn/dashboard-plugin/public'; import type { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { ApmBase } from '@elastic/apm-rum'; +import type { + SavedObjectsTaggingApi, + SavedObjectTaggingOssPluginStart, +} from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { ResolverPluginSetup } from './resolver/types'; import type { Inspect } from '../common/search_strategy'; import type { Detections } from './detections'; @@ -83,10 +87,15 @@ export interface StartPlugins { security: SecurityPluginSetup; } +export interface StartPluginsDependencies extends StartPlugins { + savedObjectsTaggingOss: SavedObjectTaggingOssPluginStart; +} + export type StartServices = CoreStart & StartPlugins & { storage: Storage; apm: ApmBase; + savedObjectsTagging?: SavedObjectsTaggingApi; }; export interface PluginSetup { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts index 477153828417b..b62994d657c3e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts @@ -46,6 +46,7 @@ import { createIndicatorMatchAlertType, createMlAlertType, createQueryAlertType, + createSavedQueryAlertType, createThresholdAlertType, } from '../../rule_types'; import { createSecurityRuleTypeWrapper } from '../../rule_types/create_security_rule_type_wrapper'; @@ -292,6 +293,19 @@ export const previewRulesRoute = async ( { create: alertInstanceFactoryStub, done: () => ({ getRecoveredAlerts: () => [] }) } ); break; + case 'saved_query': + const savedQueryAlertType = previewRuleTypeWrapper( + createSavedQueryAlertType(ruleOptions) + ); + await runExecutors( + savedQueryAlertType.executor, + savedQueryAlertType.id, + savedQueryAlertType.name, + previewRuleParams, + () => true, + { create: alertInstanceFactoryStub, done: () => ({ getRecoveredAlerts: () => [] }) } + ); + break; case 'threshold': const thresholdAlertType = previewRuleTypeWrapper( createThresholdAlertType(ruleOptions) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts index eb21579ddea87..a5c811bc1a5c1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { performance } from 'perf_hooks'; import { mergeMissingFieldsWithSource } from './merge_missing_fields_with_source'; import type { SignalSourceHit } from '../../types'; import { emptyEsResult } from '../../__mocks__/empty_signal_source_hit'; @@ -294,6 +294,16 @@ describe('merge_missing_fields_with_source', () => { 'bar.foo': [], }; + const bigFields: SignalSourceHit['fields'] = [...Array(7000).keys()].reduce( + (acc, item, index) => { + return { + [`my-runtime-field-${index}`]: ['nice'], + ...acc, + }; + }, + {} + ); + test('when source is an empty array (f_[]), merged doc is empty array (f_[])"', () => { const _source: SignalSourceHit['_source'] = { 'bar.foo': [], @@ -356,6 +366,29 @@ describe('merge_missing_fields_with_source', () => { const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source; expect(merged).toEqual(_source); }); + + /** + * tests for https://github.com/elastic/kibana/issues/135963 + * This test will fail when we replace the import + * import { set } from '@elastic/safer-lodash-set'; + * to use the fp version + * import { set } from '@elastic/safer-lodash-set/fp'; + * and switch around the return inside of filteredEntries.reduce + * to be the following: + * return set(fieldsKey, valueToMerge, merged); + */ + test('when fields is big', () => { + const _source: SignalSourceHit['_source'] = { + 'bar.foo': [], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields: bigFields }; + const start = performance.now(); + // we don't care about the response just determining performance + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source; + const end = performance.now(); + expect(end - start).toBeLessThan(500); + }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.ts index 28269652ae5e8..89695f6b562b0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/source_fields_merging/strategies/merge_missing_fields_with_source.ts @@ -6,7 +6,7 @@ */ import { get } from 'lodash/fp'; -import { set } from '@elastic/safer-lodash-set/fp'; +import { set } from '@elastic/safer-lodash-set'; import type { SignalSource } from '../../types'; import { filterFieldEntries } from '../utils/filter_field_entries'; import type { FieldsType, MergeStrategyFunction } from '../types'; @@ -44,7 +44,7 @@ export const mergeMissingFieldsWithSource: MergeStrategyFunction = ({ doc, ignor const valueInMergedDocument = get(fieldsKey, merged); const valueToMerge = recursiveUnboxingFields(fieldsValue, valueInMergedDocument); - return set(fieldsKey, valueToMerge, merged); + return set(merged, fieldsKey, valueToMerge); }, { ...source } ); diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/rule_common_expressions/rule_common_expressions.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/rule_common_expressions/rule_common_expressions.tsx index 684b340170139..0f907597b6702 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/rule_common_expressions/rule_common_expressions.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/rule_common_expressions/rule_common_expressions.tsx @@ -18,6 +18,7 @@ import { import { CommonAlertParams } from '../types'; import { DEFAULT_VALUES } from '../constants'; import { TestQueryRow, TestQueryRowProps } from '../test_query_row'; +import { QueryThresholdHelpPopover } from './threshold_help_popover'; export interface RuleCommonExpressionsProps { thresholdComparator?: CommonAlertParams['thresholdComparator']; @@ -57,12 +58,13 @@ export const RuleCommonExpressions: React.FC = ({ return ( <> -
    +

    -

    + defaultMessage="Set the threshold and time window" + />{' '} + +
    { + state: State = { + isPopoverOpen: false, + }; + + PopoverStyles = css` + max-width: 400px; + `; + + _togglePopover = () => { + this.setState((prevState) => ({ + isPopoverOpen: !prevState.isPopoverOpen, + })); + }; + + _closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + }; + + _renderContent() { + return ( +
    + +

    + +

    +

    + Check every, + }} + /> +

    +
    + + +
    + ); + } + + render() { + return ( + + } + isOpen={this.state.isPopoverOpen} + closePopover={this._closePopover} + repositionOnScroll + ownFocus + > + + + + {this._renderContent()} + + ); + } +} diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_edit_extension_wrapper.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_edit_extension_wrapper.tsx index bffdc882115a0..abe156475755d 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_edit_extension_wrapper.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_edit_extension_wrapper.tsx @@ -6,7 +6,10 @@ */ import React, { memo, useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; import { PackagePolicyEditExtensionComponentProps } from '@kbn/fleet-plugin/public'; +import { EuiButton, EuiCallOut } from '@elastic/eui'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; import { PolicyConfig, MonitorFields } from './types'; import { ConfigKey, DataStream, TLSFields } from './types'; import { SyntheticsPolicyEditExtension } from './synthetics_policy_edit_extension'; @@ -95,6 +98,20 @@ export const SyntheticsPolicyEditExtensionWrapper = memo +

    {EDIT_IN_UPTIME_DESC}

    + {/* TODO Add a link to exact monitor*/} + + {EDIT_IN_UPTIME_LABEL} + + + ); + } + return ( { +// FLAKY: https://github.com/elastic/kibana/issues/131346 +describe.skip('MonitorPage', () => { it('renders expected elements for valid props', async () => { const { findByText, findByPlaceholderText } = render(); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 750bc121875b4..780ea4fe5f40c 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -3642,14 +3642,12 @@ "expressionTagcloud.renderer.tagcloud.helpDescription": "Afficher le rendu d'un nuage de balises", "expressionXY.annotationLayer.annotations.help": "Annotations", "expressionXY.annotationLayer.help": "Configurer un calque d'annotation dans le graphique xy", - "expressionXY.annotationLayer.hide.help": "Afficher/masquer les détails", "expressionXY.axisExtentConfig.extentMode.help": "Mode d'extension", "expressionXY.axisExtentConfig.help": "Configurer les étendues d'axe du graphique xy", "expressionXY.axisExtentConfig.lowerBound.help": "Limite inférieure", "expressionXY.axisExtentConfig.upperBound.help": "Limite supérieure", "expressionXY.dataLayer.accessors.help": "Les colonnes à afficher sur l'axe y.", "expressionXY.dataLayer.help": "Configurer un calque dans le graphique xy", - "expressionXY.dataLayer.hide.help": "Afficher/masquer l'axe", "expressionXY.dataLayer.isHistogram.help": "Disposer le graphique sous forme d'histogramme ou non", "expressionXY.dataLayer.lineWidth.help": "Largeur de la ligne", "expressionXY.dataLayer.markSizeAccessor.help": "Accesseur de taille de marque", @@ -10441,14 +10439,7 @@ "xpack.csp.cspHealthBadge.criticalLabel": "Critique", "xpack.csp.cspHealthBadge.healthyLabel": "Intègre", "xpack.csp.cspHealthBadge.warningLabel": "Avertissement", - "xpack.csp.cspPageTemplate.defaultNoDataConfig.pageTitle": "Aucune donnée trouvée", - "xpack.csp.cspPageTemplate.defaultNoDataConfig.solutionNameLabel": "Niveau de sécurité du cloud", - "xpack.csp.cspPageTemplate.loadingDescription": "Chargement...", "xpack.csp.cspPageTemplate.navigationTitle": "Niveau de sécurité du cloud", - "xpack.csp.cspPageTemplate.packageNotInstalled.buttonLabel": "Ajouter une intégration CIS", - "xpack.csp.cspPageTemplate.packageNotInstalled.description": "Utilisez notre intégration CIS Kubernetes Benchmark pour mesurer votre configuration de cluster Kubernetes par rapport aux recommandations du CIS.", - "xpack.csp.cspPageTemplate.packageNotInstalled.pageTitle": "Installer l'intégration pour commencer", - "xpack.csp.cspPageTemplate.packageNotInstalled.solutionNameLabel": "Niveau de sécurité du cloud", "xpack.csp.cspSettings.rules": "Règles de sécurité du CSP - ", "xpack.csp.dashboard.risksTable.cisSectionColumnLabel": "Section CIS", "xpack.csp.expandColumnDescriptionLabel": "Développer", @@ -10468,9 +10459,6 @@ "xpack.csp.findings.resourceFindings.backToResourcesPageButtonLabel": "Retour à la vue de regroupement par ressource", "xpack.csp.findings.searchBar.searchPlaceholder": "Rechercher dans les résultats (par ex. rule.section.keyword : \"serveur d'API\")", "xpack.csp.navigation.cloudPostureBreadcrumbLabel": "Niveau du cloud", - "xpack.csp.pageTemplate.errorDetails.errorBodyTitle": "{body}", - "xpack.csp.pageTemplate.errorDetails.errorCodeTitle": "{error} {statusCode}", - "xpack.csp.pageTemplate.loadErrorMessage": "Nous n'avons pas pu récupérer vos données sur le niveau de sécurité du cloud.", "xpack.csp.rules.activateAllButtonLabel": "Activer {count, plural, one {# règle} other {# règles}}", "xpack.csp.rules.clearSelectionButtonLabel": "Effacer la sélection", "xpack.csp.rules.deactivateAllButtonLabel": "Désactiver {count, plural, one {# règle} other {# règles}}", @@ -10528,7 +10516,6 @@ "xpack.dataVisualizer.dataGrid.field.topValues.calculatedFromSampleDescription": "Calculé à partir d'un échantillon de {topValuesSamplerShardSize} documents par partition", "xpack.dataVisualizer.dataGrid.field.topValuesLabel": "Valeurs les plus élevées", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.falseCountLabel": "faux", - "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.summaryTableTitle": "Résumé", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.trueCountLabel": "vrai", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.choroplethMapTopValues.calculatedFromSampleDescription": "Calculé à partir d'un échantillon de {topValuesSamplerShardSize} documents par partition", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.documentStatsTable.countLabel": "compte", @@ -11642,11 +11629,6 @@ "xpack.enterpriseSearch.appSearch.tokens.search.name": "Clé de recherche publique", "xpack.enterpriseSearch.appSearch.tokens.update": "La clé d'API \"{name}\" a été mise à jour", "xpack.enterpriseSearch.content.description": "Enterprise Search offre un certain nombre de moyens de rendre vos données facilement interrogeables. Vous pouvez choisir entre le robot d'indexation, les indices Elasticsearch, l'API, les téléchargements directs ou les connecteurs tiers.", - "xpack.enterpriseSearch.content.nav.appSearchTitle": "App Search", - "xpack.enterpriseSearch.content.nav.contentTitle": "Contenu", - "xpack.enterpriseSearch.content.nav.enterpriseSearchOverviewTitle": "Aperçu", - "xpack.enterpriseSearch.content.nav.searchIndicesTitle": "Rechercher dans les index", - "xpack.enterpriseSearch.content.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.content.navTitle": "Contenu", "xpack.enterpriseSearch.content.newIndex.breadcrumb": "Nouvel index de recherche", "xpack.enterpriseSearch.content.newIndex.buttonGroup.api.description": "Utiliser différentes bibliothèques de clients pour ajouter des documents à votre index de recherche", @@ -11842,7 +11824,6 @@ "xpack.enterpriseSearch.crawler.urlComboBox.invalidUrlErrorMessage": "Veuillez entrer une URL valide", "xpack.enterpriseSearch.curations.settings.licenseUpgradeLink": "En savoir plus sur les mises à niveau incluses dans la licence", "xpack.enterpriseSearch.curations.settings.start30DayTrialButtonLabel": "Démarrer un essai gratuit de 30 jours", - "xpack.enterpriseSearch.elasticsearch.nav.contentTitle": "Elasticsearch", "xpack.enterpriseSearch.elasticsearch.productCardDescription": "Concevez et créez des applications de recherche performantes et pertinentes ou des implémentations de recherche à grande échelle directement dans Elasticsearch.", "xpack.enterpriseSearch.elasticsearch.productDescription": "Outils de bas niveau pour la création d'expériences performantes et pertinentes.", "xpack.enterpriseSearch.elasticsearch.productName": "Elasticsearch", @@ -11873,6 +11854,11 @@ "xpack.enterpriseSearch.licenseCalloutBody": "L'authentification d'Enterprise via SAML, la prise en charge des autorisations de niveau document, les expériences de recherche personnalisées et bien plus encore sont disponibles avec une licence Platinum valide.", "xpack.enterpriseSearch.licenseDocumentationLink": "En savoir plus sur les fonctionnalités incluses dans la licence", "xpack.enterpriseSearch.licenseManagementLink": "Gérer votre licence", + "xpack.enterpriseSearch.nav.appSearchTitle": "App Search", + "xpack.enterpriseSearch.nav.contentTitle": "Contenu", + "xpack.enterpriseSearch.nav.enterpriseSearchOverviewTitle": "Aperçu", + "xpack.enterpriseSearch.nav.searchIndicesTitle": "Rechercher dans les index", + "xpack.enterpriseSearch.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.notFound.action1": "Retour à votre tableau de bord", "xpack.enterpriseSearch.notFound.action2": "Contacter le support technique", "xpack.enterpriseSearch.notFound.description": "Impossible de trouver la page que vous recherchez.", @@ -17409,7 +17395,6 @@ "xpack.maps.drawTooltip.lineInstructions": "Cliquez pour commencer la ligne. Cliquez pour ajouter le vertex. Double-cliquez pour terminer.", "xpack.maps.drawTooltip.pointInstructions": "Cliquez pour créer un point.", "xpack.maps.drawTooltip.polygonInstructions": "Cliquez pour commencer la forme. Cliquez pour ajouter le vertex. Double-cliquez pour terminer.", - "xpack.maps.embeddable.boundsFilterLabel": "Limites de carte au centre : {lat}, {lon}, zoom : {zoom}", "xpack.maps.embeddableDisplayName": "carte", "xpack.maps.emsFileSelect.selectPlaceholder": "Sélectionner les limites EMS", "xpack.maps.emsSource.tooltipsTitle": "Champs d'infobulle", @@ -17439,8 +17424,6 @@ "xpack.maps.fileUploadWizard.disabledDesc": "Impossible de charger les fichiers, vous ne disposez pas du privilège Kibana de gestion des vues de données.", "xpack.maps.fileUploadWizard.title": "Charger le fichier", "xpack.maps.fileUploadWizard.uploadLabel": "Importation du fichier", - "xpack.maps.filterByMapExtentMenuItem.disableDisplayName": "Désactiver le filtre par étendue de carte", - "xpack.maps.filterByMapExtentMenuItem.enableDisplayName": "Activer le filtre par étendue de carte", "xpack.maps.filterEditor.applyForceRefreshLabel": "Appliquer une actualisation globale aux données de calque", "xpack.maps.filterEditor.applyForceRefreshTooltip": "Lorsque cette option est activée, le calque récupère à nouveau les données au moment de l’actualisation automatique ainsi que chaque fois que le bouton \"Actualiser\" est sélectionné.", "xpack.maps.filterEditor.applyGlobalFilterHelp": "Lorsque cette option est activée, les résultats sont affinés par recherche globale.", @@ -19170,8 +19153,6 @@ "xpack.ml.itemsGrid.itemsPerPageButtonLabel": "Éléments par page : {itemsPerPage}", "xpack.ml.itemsGrid.noItemsAddedTitle": "Aucun élément n'a été ajouté", "xpack.ml.itemsGrid.noMatchingItemsTitle": "Aucun élément correspondant", - "xpack.ml.jobDetails.datafeedChartAriaLabel": "Graphique de flux de données", - "xpack.ml.jobDetails.datafeedChartTooltipText": "Graphique de flux de données", "xpack.ml.jobMessages.actionsLabel": "Actions", "xpack.ml.jobMessages.clearJobAuditMessagesDisabledTooltip": "Effacement des notifications non pris en charge.", "xpack.ml.jobMessages.clearJobAuditMessagesErrorTitle": "Erreur lors de l'effacement des avertissements et erreurs du message lié à la tâche", @@ -22555,30 +22536,9 @@ "xpack.observability.rules.deleteSelectedIdsErrorNotification.descriptionText": "Impossible de supprimer {numErrors, number} {numErrors, plural, one {{singleTitle}} other {{multipleTitle}}}", "xpack.observability.rules.deleteSelectedIdsSuccessNotification.descriptionText": "Suppression de {numSuccesses, number} {numSuccesses, plural, one {{singleTitle}} other {{multipleTitle}}} effectuée", "xpack.observability.rules.docsLinkText": "Documentation", - "xpack.observability.rules.emptyPrompt.emptyButton": "Créer une règle", - "xpack.observability.rules.emptyPrompt.emptyTitle": "Créer votre première règle", "xpack.observability.rules.loadError": "Impossible de charger les règles", - "xpack.observability.rules.manageLicense.manageLicenseCancelButtonText": "Annuler", - "xpack.observability.rules.manageLicense.manageLicenseConfirmButtonText": "Gérer la licence", - "xpack.observability.rules.manageLicense.manageLicenseMessage": "Le type de règle {ruleTypeId} est désactivé, car il requiert une licence {licenseRequired}. Continuez vers Gestion des licences pour afficher les options de mise à niveau.", - "xpack.observability.rules.manageLicense.manageLicenseTitle": "Licence {licenseRequired} requise", - "xpack.observability.rules.noDataPrompt.noDataDesc": "Les règles permettent de recevoir des alertes et d'automatiser des actions personnalisées lorsque des conditions spécifiques sont satisfaites.", - "xpack.observability.rules.noPermissionToCreateDescription": "Contactez votre administrateur système.", - "xpack.observability.rules.noPermissionToCreateTitle": "Aucune autorisation pour créer des règles", - "xpack.observability.rules.refreshRulesButtonLabel": "Actualiser", - "xpack.observability.rules.ruleLastResponseFilterLabel": "Dernière réponse", "xpack.observability.rules.rulesTable.changeStatusAriaLabel": "Modifier le statut", - "xpack.observability.rules.rulesTable.columns.actionsTitle": "Actions", - "xpack.observability.rules.rulesTable.columns.deleteAriaLabel": "Supprimer", - "xpack.observability.rules.rulesTable.columns.deleteButtonTooltip": "Supprimer", - "xpack.observability.rules.rulesTable.columns.editAriaLabel": "Modifier", - "xpack.observability.rules.rulesTable.columns.editButtonTooltip": "Modifier", "xpack.observability.rules.rulesTable.columns.lastResponseTitle": "Dernière réponse", - "xpack.observability.rules.rulesTable.columns.lastRunTitle": "Dernière exécution", - "xpack.observability.rules.rulesTable.columns.nameTitle": "Règle", - "xpack.observability.rules.rulesTable.columns.statusTitle": "Statut", - "xpack.observability.rules.rulesTable.fixLicenseLink": "Corriger", - "xpack.observability.rules.rulesTable.pluralTitle": "règles", "xpack.observability.rules.rulesTable.ruleStatusActive": "Actif", "xpack.observability.rules.rulesTable.ruleStatusError": "Erreur", "xpack.observability.rules.rulesTable.ruleStatusLicenseError": "Erreur de licence", @@ -22586,10 +22546,6 @@ "xpack.observability.rules.rulesTable.ruleStatusPending": "En attente", "xpack.observability.rules.rulesTable.ruleStatusUnknown": "Inconnu", "xpack.observability.rules.rulesTable.ruleStatusWarning": "avertissement", - "xpack.observability.rules.rulesTable.singleTitle": "règle", - "xpack.observability.rules.searchPlaceholderTitle": "Recherche", - "xpack.observability.rules.totalItemsCountDescription": "Affichage : {pageSize} sur {totalItemCount} règles", - "xpack.observability.rules.typeFilterLabel": "Type", "xpack.observability.rulesLinkTitle": "Règles", "xpack.observability.rulesList.unableToLoadRuleTags": "Impossible de charger les balises de règle", "xpack.observability.rulesTitle": "Règles", @@ -31712,7 +31668,6 @@ "xpack.ux.overview.beatsCard.title": "Ajouter les données RUM", "xpack.ux.overview.heading": "Tableau de bord", "xpack.ux.overview.solutionName": "Observabilité", - "xpack.ux.pageViews.analyze": "Analyser", "xpack.ux.percentile.50thMedian": "50e (médiane)", "xpack.ux.percentile.75th": "75e", "xpack.ux.percentile.90th": "90e", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 0ca4cbaa696b7..5f076322b4917 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3640,14 +3640,12 @@ "expressionTagcloud.renderer.tagcloud.helpDescription": "Tag Cloudを表示", "expressionXY.annotationLayer.annotations.help": "注釈", "expressionXY.annotationLayer.help": "xyグラフで注釈レイヤーを構成", - "expressionXY.annotationLayer.hide.help": "詳細を表示/非表示", "expressionXY.axisExtentConfig.extentMode.help": "範囲モード", "expressionXY.axisExtentConfig.help": "xyグラフの軸範囲を構成", "expressionXY.axisExtentConfig.lowerBound.help": "下界", "expressionXY.axisExtentConfig.upperBound.help": "上界", "expressionXY.dataLayer.accessors.help": "y軸に表示する列。", "expressionXY.dataLayer.help": "xyグラフでレイヤーを構成", - "expressionXY.dataLayer.hide.help": "軸を表示/非表示", "expressionXY.dataLayer.isHistogram.help": "グラフをヒストグラムとしてレイアウトするかどうか", "expressionXY.dataLayer.lineWidth.help": "線の幅", "expressionXY.dataLayer.markSizeAccessor.help": "マークサイズアクセラレーター", @@ -10433,14 +10431,7 @@ "xpack.csp.cspHealthBadge.criticalLabel": "重大", "xpack.csp.cspHealthBadge.healthyLabel": "正常", "xpack.csp.cspHealthBadge.warningLabel": "警告", - "xpack.csp.cspPageTemplate.defaultNoDataConfig.pageTitle": "データが見つかりません", - "xpack.csp.cspPageTemplate.defaultNoDataConfig.solutionNameLabel": "クラウドセキュリティ態勢", - "xpack.csp.cspPageTemplate.loadingDescription": "読み込み中...", "xpack.csp.cspPageTemplate.navigationTitle": "クラウドセキュリティ態勢", - "xpack.csp.cspPageTemplate.packageNotInstalled.buttonLabel": "CIS統合を追加", - "xpack.csp.cspPageTemplate.packageNotInstalled.description": "CIS Kubernetes Benchmark統合は、CISの推奨事項に照らしてKubernetesクラスター設定を測定します。", - "xpack.csp.cspPageTemplate.packageNotInstalled.pageTitle": "開始するには統合をインストールしてください", - "xpack.csp.cspPageTemplate.packageNotInstalled.solutionNameLabel": "クラウドセキュリティ態勢", "xpack.csp.cspSettings.rules": "CSPセキュリティルール - ", "xpack.csp.dashboard.risksTable.cisSectionColumnLabel": "CISセクション", "xpack.csp.expandColumnDescriptionLabel": "拡張", @@ -10460,9 +10451,6 @@ "xpack.csp.findings.resourceFindings.backToResourcesPageButtonLabel": "リソース別グループビューに戻る", "xpack.csp.findings.searchBar.searchPlaceholder": "検索結果(例:rule.section.keyword:\"API Server\")", "xpack.csp.navigation.cloudPostureBreadcrumbLabel": "クラウド態勢", - "xpack.csp.pageTemplate.errorDetails.errorBodyTitle": "{body}", - "xpack.csp.pageTemplate.errorDetails.errorCodeTitle": "{error} {statusCode}", - "xpack.csp.pageTemplate.loadErrorMessage": "クラウドセキュリティ態勢データを取得できませんでした", "xpack.csp.rules.activateAllButtonLabel": "{count, plural, other {#個のルール}}をアクティブ化", "xpack.csp.rules.clearSelectionButtonLabel": "選択した項目をクリア", "xpack.csp.rules.deactivateAllButtonLabel": "{count, plural, other {#個のルール}}を非アクティブ化", @@ -10520,7 +10508,6 @@ "xpack.dataVisualizer.dataGrid.field.topValues.calculatedFromSampleDescription": "1 つのシャードにつき {topValuesSamplerShardSize} のドキュメントのサンプルで計算されています", "xpack.dataVisualizer.dataGrid.field.topValuesLabel": "トップの値", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.falseCountLabel": "false", - "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.summaryTableTitle": "まとめ", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.trueCountLabel": "true", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.choroplethMapTopValues.calculatedFromSampleDescription": "1 つのシャードにつき {topValuesSamplerShardSize} のドキュメントのサンプルで計算されています", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.documentStatsTable.countLabel": "カウント", @@ -11633,11 +11620,6 @@ "xpack.enterpriseSearch.appSearch.tokens.search.name": "公開検索キー", "xpack.enterpriseSearch.appSearch.tokens.update": "APIキー'{name}'が更新されました", "xpack.enterpriseSearch.content.description": "エンタープライズ サーチでは、さまざまな方法で簡単にデータを検索可能にできます。Webクローラー、Elasticsearchインデックス、API、直接アップロード、サードパーティコネクターから選択します。", - "xpack.enterpriseSearch.content.nav.appSearchTitle": "App Search", - "xpack.enterpriseSearch.content.nav.contentTitle": "コンテンツ", - "xpack.enterpriseSearch.content.nav.enterpriseSearchOverviewTitle": "概要", - "xpack.enterpriseSearch.content.nav.searchIndicesTitle": "インデックスの検索", - "xpack.enterpriseSearch.content.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.content.navTitle": "コンテンツ", "xpack.enterpriseSearch.content.newIndex.breadcrumb": "新しい検索インデックス", "xpack.enterpriseSearch.content.newIndex.buttonGroup.api.description": "さまざまなクライアントライブラリを使用して、ドキュメントを検索インデックスに追加", @@ -11833,7 +11815,6 @@ "xpack.enterpriseSearch.crawler.urlComboBox.invalidUrlErrorMessage": "有効なURLを入力してください", "xpack.enterpriseSearch.curations.settings.licenseUpgradeLink": "ライセンスアップグレードの詳細", "xpack.enterpriseSearch.curations.settings.start30DayTrialButtonLabel": "30 日間のトライアルの開始", - "xpack.enterpriseSearch.elasticsearch.nav.contentTitle": "Elasticsearch", "xpack.enterpriseSearch.elasticsearch.productCardDescription": "Elasticsearchで直接、パフォーマンスと関連性が高い、検索対応アプリケーションまたは大規模検索実装を設計して構築。", "xpack.enterpriseSearch.elasticsearch.productDescription": "高パフォーマンスで関連性の高い検索エクスペリエンスを作成するための低レベルのツール。", "xpack.enterpriseSearch.elasticsearch.productName": "Elasticsearch", @@ -11864,6 +11845,12 @@ "xpack.enterpriseSearch.licenseCalloutBody": "SAML経由のエンタープライズ認証、ドキュメントレベルのアクセス権と許可サポート、カスタム検索経験などは有効なPlatinumライセンスで提供されます。", "xpack.enterpriseSearch.licenseDocumentationLink": "ライセンス機能の詳細", "xpack.enterpriseSearch.licenseManagementLink": "ライセンスを更新", + "xpack.enterpriseSearch.nav.appSearchTitle": "App Search", + "xpack.enterpriseSearch.nav.contentTitle": "コンテンツ", + "xpack.enterpriseSearch.nav.elasticsearchTitle": "Elasticsearch", + "xpack.enterpriseSearch.nav.enterpriseSearchOverviewTitle": "概要", + "xpack.enterpriseSearch.nav.searchIndicesTitle": "インデックスの検索", + "xpack.enterpriseSearch.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.notFound.action1": "ダッシュボードに戻す", "xpack.enterpriseSearch.notFound.action2": "サポートに問い合わせる", "xpack.enterpriseSearch.notFound.description": "お探しのページは見つかりませんでした。", @@ -17399,7 +17386,6 @@ "xpack.maps.drawTooltip.lineInstructions": "クリックして行を開始します。クリックして頂点を追加します。ダブルクリックして終了します。", "xpack.maps.drawTooltip.pointInstructions": "クリックして点を作成します。", "xpack.maps.drawTooltip.polygonInstructions": "クリックしてシェイプを開始します。クリックして頂点を追加します。ダブルクリックして終了します。", - "xpack.maps.embeddable.boundsFilterLabel": "中央のマップの境界:{lat}、{lon}、ズーム:{zoom}", "xpack.maps.embeddableDisplayName": "マップ", "xpack.maps.emsFileSelect.selectPlaceholder": "EMS境界を選択", "xpack.maps.emsSource.tooltipsTitle": "ツールチップフィールド", @@ -17429,8 +17415,6 @@ "xpack.maps.fileUploadWizard.disabledDesc": "ファイルをアップロードできません。Kibana「データビュー管理」権限がありません。", "xpack.maps.fileUploadWizard.title": "ファイルをアップロード", "xpack.maps.fileUploadWizard.uploadLabel": "ファイルをインポートしています", - "xpack.maps.filterByMapExtentMenuItem.disableDisplayName": "マップ範囲でのフィルターを無効にする", - "xpack.maps.filterByMapExtentMenuItem.enableDisplayName": "マップ範囲でのフィルターを有効にする", "xpack.maps.filterEditor.applyForceRefreshLabel": "レイヤーデータにグローバル更新を適用", "xpack.maps.filterEditor.applyForceRefreshTooltip": "有効にすると、自動更新が実行されるときと、[更新]をクリックしたときに、レイヤーでデータが再取り込みされます。", "xpack.maps.filterEditor.applyGlobalFilterHelp": "有効にすると、結果がグローバル検索で絞り込まれます", @@ -19161,8 +19145,6 @@ "xpack.ml.itemsGrid.itemsPerPageButtonLabel": "ページごとの項目数:{itemsPerPage}", "xpack.ml.itemsGrid.noItemsAddedTitle": "項目が追加されていません", "xpack.ml.itemsGrid.noMatchingItemsTitle": "一致する項目が見つかりません。", - "xpack.ml.jobDetails.datafeedChartAriaLabel": "データフィードグラフ", - "xpack.ml.jobDetails.datafeedChartTooltipText": "データフィードグラフ", "xpack.ml.jobMessages.actionsLabel": "アクション", "xpack.ml.jobMessages.clearJobAuditMessagesDisabledTooltip": "通知の消去はサポートされていません。", "xpack.ml.jobMessages.clearJobAuditMessagesErrorTitle": "ジョブメッセージ警告とエラーの消去エラー", @@ -22541,30 +22523,9 @@ "xpack.observability.rules.deleteSelectedIdsErrorNotification.descriptionText": "{numErrors, number} {numErrors, plural, one {{singleTitle}} other {{multipleTitle}}}を削除できませんでした", "xpack.observability.rules.deleteSelectedIdsSuccessNotification.descriptionText": "{numSuccesses, number} {numSuccesses, plural, one {{singleTitle}} other {{multipleTitle}}}を削除しました", "xpack.observability.rules.docsLinkText": "ドキュメント", - "xpack.observability.rules.emptyPrompt.emptyButton": "ルールの作成", - "xpack.observability.rules.emptyPrompt.emptyTitle": "最初のルールを作成", "xpack.observability.rules.loadError": "ルールを読み込めません", - "xpack.observability.rules.manageLicense.manageLicenseCancelButtonText": "キャンセル", - "xpack.observability.rules.manageLicense.manageLicenseConfirmButtonText": "ライセンスの管理", - "xpack.observability.rules.manageLicense.manageLicenseMessage": "ルールタイプ{ruleTypeId}は無効です。{licenseRequired}ライセンスが必要です。アップグレードオプションを表示するには、[ライセンス管理]に移動してください。", - "xpack.observability.rules.manageLicense.manageLicenseTitle": "{licenseRequired}ライセンスが必要です", - "xpack.observability.rules.noDataPrompt.noDataDesc": "ルールでは、特定の条件が満たされたときに、アラートを受信し、カスタムアクションを自動化できます。", - "xpack.observability.rules.noPermissionToCreateDescription": "システム管理者にお問い合わせください。", - "xpack.observability.rules.noPermissionToCreateTitle": "ルールを作成する権限がありません", - "xpack.observability.rules.refreshRulesButtonLabel": "更新", - "xpack.observability.rules.ruleLastResponseFilterLabel": "前回の応答", "xpack.observability.rules.rulesTable.changeStatusAriaLabel": "ステータスの変更", - "xpack.observability.rules.rulesTable.columns.actionsTitle": "アクション", - "xpack.observability.rules.rulesTable.columns.deleteAriaLabel": "削除", - "xpack.observability.rules.rulesTable.columns.deleteButtonTooltip": "削除", - "xpack.observability.rules.rulesTable.columns.editAriaLabel": "編集", - "xpack.observability.rules.rulesTable.columns.editButtonTooltip": "編集", "xpack.observability.rules.rulesTable.columns.lastResponseTitle": "前回の応答", - "xpack.observability.rules.rulesTable.columns.lastRunTitle": "前回の実行", - "xpack.observability.rules.rulesTable.columns.nameTitle": "ルール", - "xpack.observability.rules.rulesTable.columns.statusTitle": "ステータス", - "xpack.observability.rules.rulesTable.fixLicenseLink": "修正", - "xpack.observability.rules.rulesTable.pluralTitle": "ルール", "xpack.observability.rules.rulesTable.ruleStatusActive": "アクティブ", "xpack.observability.rules.rulesTable.ruleStatusError": "エラー", "xpack.observability.rules.rulesTable.ruleStatusLicenseError": "ライセンスエラー", @@ -22572,10 +22533,6 @@ "xpack.observability.rules.rulesTable.ruleStatusPending": "保留中", "xpack.observability.rules.rulesTable.ruleStatusUnknown": "不明", "xpack.observability.rules.rulesTable.ruleStatusWarning": "警告", - "xpack.observability.rules.rulesTable.singleTitle": "ルール", - "xpack.observability.rules.searchPlaceholderTitle": "検索", - "xpack.observability.rules.totalItemsCountDescription": "{pageSize}/{totalItemCount}件のルールを表示しています", - "xpack.observability.rules.typeFilterLabel": "型", "xpack.observability.rulesLinkTitle": "ルール", "xpack.observability.rulesList.unableToLoadRuleTags": "ルールタグを読み込めません", "xpack.observability.rulesTitle": "ルール", @@ -31694,7 +31651,6 @@ "xpack.ux.overview.beatsCard.title": "RUMデータを追加", "xpack.ux.overview.heading": "ダッシュボード", "xpack.ux.overview.solutionName": "Observability", - "xpack.ux.pageViews.analyze": "分析", "xpack.ux.percentile.50thMedian": "50 番目(中央値)", "xpack.ux.percentile.75th": "75番目", "xpack.ux.percentile.90th": "90番目", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 9d3b92f48be3e..5f8dc58573275 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3644,14 +3644,13 @@ "expressionTagcloud.renderer.tagcloud.helpDescription": "呈现标签云图", "expressionXY.annotationLayer.annotations.help": "标注", "expressionXY.annotationLayer.help": "配置 xy 图表中的标注图层", - "expressionXY.annotationLayer.hide.help": "显示/隐藏详情", + "expressionXY.annotationLayer.simpleView.help": "显示/隐藏详情", "expressionXY.axisExtentConfig.extentMode.help": "范围模式", "expressionXY.axisExtentConfig.help": "配置 xy 图表的轴范围", "expressionXY.axisExtentConfig.lowerBound.help": "下边界", "expressionXY.axisExtentConfig.upperBound.help": "上边界", "expressionXY.dataLayer.accessors.help": "要在 y 轴上显示的列。", "expressionXY.dataLayer.help": "配置 xy 图表中的图层", - "expressionXY.dataLayer.hide.help": "显示/隐藏轴", "expressionXY.dataLayer.isHistogram.help": "是否将图表布局为直方图", "expressionXY.dataLayer.lineWidth.help": "线条宽度", "expressionXY.dataLayer.markSizeAccessor.help": "标记大小访问器", @@ -10447,14 +10446,7 @@ "xpack.csp.cspHealthBadge.criticalLabel": "紧急", "xpack.csp.cspHealthBadge.healthyLabel": "运行正常", "xpack.csp.cspHealthBadge.warningLabel": "警告", - "xpack.csp.cspPageTemplate.defaultNoDataConfig.pageTitle": "未找到任何数据", - "xpack.csp.cspPageTemplate.defaultNoDataConfig.solutionNameLabel": "云安全态势", - "xpack.csp.cspPageTemplate.loadingDescription": "正在加载……", "xpack.csp.cspPageTemplate.navigationTitle": "云安全态势", - "xpack.csp.cspPageTemplate.packageNotInstalled.buttonLabel": "添加 CIS 集成", - "xpack.csp.cspPageTemplate.packageNotInstalled.description": "使用我们的 CIS Kubernetes 基准集成根据 CIS 建议衡量 Kubernetes 集群设置。", - "xpack.csp.cspPageTemplate.packageNotInstalled.pageTitle": "安装集成以开始", - "xpack.csp.cspPageTemplate.packageNotInstalled.solutionNameLabel": "云安全态势", "xpack.csp.cspSettings.rules": "CSP 安全规则 - ", "xpack.csp.dashboard.risksTable.cisSectionColumnLabel": "CIS 部分", "xpack.csp.expandColumnDescriptionLabel": "展开", @@ -10474,9 +10466,6 @@ "xpack.csp.findings.resourceFindings.backToResourcesPageButtonLabel": "返回到按资源视图分组", "xpack.csp.findings.searchBar.searchPlaceholder": "搜索结果(例如,rule.section.keyword:“APM 服务器”)", "xpack.csp.navigation.cloudPostureBreadcrumbLabel": "云态势", - "xpack.csp.pageTemplate.errorDetails.errorBodyTitle": "{body}", - "xpack.csp.pageTemplate.errorDetails.errorCodeTitle": "{error} {statusCode}", - "xpack.csp.pageTemplate.loadErrorMessage": "我们无法提取您的云安全态势数据", "xpack.csp.rules.activateAllButtonLabel": "激活 {count, plural, other {# 个规则}}", "xpack.csp.rules.clearSelectionButtonLabel": "清除所选内容", "xpack.csp.rules.deactivateAllButtonLabel": "停用 {count, plural, other {# 个规则}}", @@ -10534,7 +10523,6 @@ "xpack.dataVisualizer.dataGrid.field.topValues.calculatedFromSampleDescription": "基于每个分片的 {topValuesSamplerShardSize} 文档样例计算", "xpack.dataVisualizer.dataGrid.field.topValuesLabel": "排名最前值", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.falseCountLabel": "false", - "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.summaryTableTitle": "摘要", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.booleanContent.trueCountLabel": "true", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.choroplethMapTopValues.calculatedFromSampleDescription": "基于每个分片的 {topValuesSamplerShardSize} 文档样例计算", "xpack.dataVisualizer.dataGrid.fieldExpandedRow.documentStatsTable.countLabel": "计数", @@ -11648,11 +11636,6 @@ "xpack.enterpriseSearch.appSearch.tokens.search.name": "公有搜索密钥", "xpack.enterpriseSearch.appSearch.tokens.update": "API 密钥“{name}”已更新", "xpack.enterpriseSearch.content.description": "Enterprise Search 提供了各种方法以便您轻松搜索数据。从网络爬虫、Elasticsearch 索引、API、直接上传或第三方连接器中选择。", - "xpack.enterpriseSearch.content.nav.appSearchTitle": "App Search", - "xpack.enterpriseSearch.content.nav.contentTitle": "内容", - "xpack.enterpriseSearch.content.nav.enterpriseSearchOverviewTitle": "概览", - "xpack.enterpriseSearch.content.nav.searchIndicesTitle": "搜索索引", - "xpack.enterpriseSearch.content.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.content.navTitle": "内容", "xpack.enterpriseSearch.content.newIndex.breadcrumb": "新搜索索引", "xpack.enterpriseSearch.content.newIndex.buttonGroup.api.description": "使用一系列客户端库可将文档添加到搜索索引", @@ -11848,7 +11831,6 @@ "xpack.enterpriseSearch.crawler.urlComboBox.invalidUrlErrorMessage": "请输入有效 URL", "xpack.enterpriseSearch.curations.settings.licenseUpgradeLink": "详细了解许可证升级", "xpack.enterpriseSearch.curations.settings.start30DayTrialButtonLabel": "开始为期 30 天的试用", - "xpack.enterpriseSearch.elasticsearch.nav.contentTitle": "Elasticsearch", "xpack.enterpriseSearch.elasticsearch.productCardDescription": "直接在 Elasticsearch 中设计并构建由相关搜索提供支持的高性能应用程序或大规模搜索实现。", "xpack.enterpriseSearch.elasticsearch.productDescription": "用于打造高效、相关的搜索体验的低级工具。", "xpack.enterpriseSearch.elasticsearch.productName": "Elasticsearch", @@ -11879,6 +11861,12 @@ "xpack.enterpriseSearch.licenseCalloutBody": "使用有效的白金级许可证,可获得通过 SAML 实现的企业验证、文档级别权限和授权支持、定制搜索体验等等。", "xpack.enterpriseSearch.licenseDocumentationLink": "详细了解许可证功能", "xpack.enterpriseSearch.licenseManagementLink": "管理您的许可", + "xpack.enterpriseSearch.nav.appSearchTitle": "App Search", + "xpack.enterpriseSearch.nav.contentTitle": "内容", + "xpack.enterpriseSearch.nav.elasticsearchTitle": "Elasticsearch", + "xpack.enterpriseSearch.nav.enterpriseSearchOverviewTitle": "概览", + "xpack.enterpriseSearch.nav.searchIndicesTitle": "搜索索引", + "xpack.enterpriseSearch.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.notFound.action1": "返回到您的仪表板", "xpack.enterpriseSearch.notFound.action2": "联系支持人员", "xpack.enterpriseSearch.notFound.description": "找不到您要查找的页面。", @@ -17417,7 +17405,6 @@ "xpack.maps.drawTooltip.lineInstructions": "单击以开始绘制线条。单击以添加顶点。双击以完成。", "xpack.maps.drawTooltip.pointInstructions": "单击以创建点。", "xpack.maps.drawTooltip.polygonInstructions": "单击以开始绘制形状。单击以添加顶点。双击以完成。", - "xpack.maps.embeddable.boundsFilterLabel": "位于中心的地图边界:{lat}, {lon},缩放:{zoom}", "xpack.maps.embeddableDisplayName": "地图", "xpack.maps.emsFileSelect.selectPlaceholder": "选择 EMS 边界", "xpack.maps.emsSource.tooltipsTitle": "工具提示字段", @@ -17447,8 +17434,6 @@ "xpack.maps.fileUploadWizard.disabledDesc": "无法上传文件,您缺少对“数据视图管理”的 Kibana 权限。", "xpack.maps.fileUploadWizard.title": "上传文件", "xpack.maps.fileUploadWizard.uploadLabel": "正在导入文件", - "xpack.maps.filterByMapExtentMenuItem.disableDisplayName": "按地图范围禁用筛选", - "xpack.maps.filterByMapExtentMenuItem.enableDisplayName": "按地图范围启用筛选", "xpack.maps.filterEditor.applyForceRefreshLabel": "将全局刷新应用于图层数据", "xpack.maps.filterEditor.applyForceRefreshTooltip": "启用后,图层将在触发自动刷新和单击“刷新”时重新提取数据。", "xpack.maps.filterEditor.applyGlobalFilterHelp": "启用后,全局搜索会缩减结果", @@ -19181,8 +19166,6 @@ "xpack.ml.itemsGrid.itemsPerPageButtonLabel": "每页中的项:{itemsPerPage}", "xpack.ml.itemsGrid.noItemsAddedTitle": "没有添加任何项", "xpack.ml.itemsGrid.noMatchingItemsTitle": "没有匹配的项", - "xpack.ml.jobDetails.datafeedChartAriaLabel": "数据馈送图表", - "xpack.ml.jobDetails.datafeedChartTooltipText": "数据馈送图表", "xpack.ml.jobMessages.actionsLabel": "操作", "xpack.ml.jobMessages.clearJobAuditMessagesDisabledTooltip": "不支持清除通知。", "xpack.ml.jobMessages.clearJobAuditMessagesErrorTitle": "清除作业消息警告和错误时出错", @@ -22565,30 +22548,9 @@ "xpack.observability.rules.deleteSelectedIdsConfirmModal.descriptionText": "无法恢复{numIdsToDelete, plural, one {删除的{singleTitle}} other {删除的{multipleTitle}}}。", "xpack.observability.rules.deleteSelectedIdsErrorNotification.descriptionText": "无法删除 {numErrors, number} 个{numErrors, plural, one {{singleTitle}} other {{multipleTitle}}}", "xpack.observability.rules.docsLinkText": "文档", - "xpack.observability.rules.emptyPrompt.emptyButton": "创建规则", - "xpack.observability.rules.emptyPrompt.emptyTitle": "创建您的首个规则", "xpack.observability.rules.loadError": "无法加载规则", - "xpack.observability.rules.manageLicense.manageLicenseCancelButtonText": "取消", - "xpack.observability.rules.manageLicense.manageLicenseConfirmButtonText": "管理许可证", - "xpack.observability.rules.manageLicense.manageLicenseMessage": "规则类型 {ruleTypeId} 已禁用,因为它需要{licenseRequired}许可证。继续前往“许可证管理”查看升级选项。", - "xpack.observability.rules.manageLicense.manageLicenseTitle": "需要{licenseRequired}许可证", - "xpack.observability.rules.noDataPrompt.noDataDesc": "规则允许您接收告警并在满足特定条件时自动完成定制操作。", - "xpack.observability.rules.noPermissionToCreateDescription": "请联系您的系统管理员。", - "xpack.observability.rules.noPermissionToCreateTitle": "没有创建规则的权限", - "xpack.observability.rules.refreshRulesButtonLabel": "刷新", - "xpack.observability.rules.ruleLastResponseFilterLabel": "上次响应", "xpack.observability.rules.rulesTable.changeStatusAriaLabel": "更改状态", - "xpack.observability.rules.rulesTable.columns.actionsTitle": "操作", - "xpack.observability.rules.rulesTable.columns.deleteAriaLabel": "删除", - "xpack.observability.rules.rulesTable.columns.deleteButtonTooltip": "删除", - "xpack.observability.rules.rulesTable.columns.editAriaLabel": "编辑", - "xpack.observability.rules.rulesTable.columns.editButtonTooltip": "编辑", "xpack.observability.rules.rulesTable.columns.lastResponseTitle": "上次响应", - "xpack.observability.rules.rulesTable.columns.lastRunTitle": "上次运行", - "xpack.observability.rules.rulesTable.columns.nameTitle": "规则", - "xpack.observability.rules.rulesTable.columns.statusTitle": "状态", - "xpack.observability.rules.rulesTable.fixLicenseLink": "修复", - "xpack.observability.rules.rulesTable.pluralTitle": "规则", "xpack.observability.rules.rulesTable.ruleStatusActive": "活动", "xpack.observability.rules.rulesTable.ruleStatusError": "错误", "xpack.observability.rules.rulesTable.ruleStatusLicenseError": "许可证错误", @@ -22596,10 +22558,6 @@ "xpack.observability.rules.rulesTable.ruleStatusPending": "待处理", "xpack.observability.rules.rulesTable.ruleStatusUnknown": "未知", "xpack.observability.rules.rulesTable.ruleStatusWarning": "警告", - "xpack.observability.rules.rulesTable.singleTitle": "规则", - "xpack.observability.rules.searchPlaceholderTitle": "搜索", - "xpack.observability.rules.totalItemsCountDescription": "正在显示:{pageSize} 个规则(共 {totalItemCount} 个)", - "xpack.observability.rules.typeFilterLabel": "类型", "xpack.observability.rulesLinkTitle": "规则", "xpack.observability.rulesList.unableToLoadRuleTags": "无法加载规则标签", "xpack.observability.rulesTitle": "规则", @@ -31723,7 +31681,6 @@ "xpack.ux.overview.beatsCard.title": "添加 RUM 数据", "xpack.ux.overview.heading": "仪表板", "xpack.ux.overview.solutionName": "Observability", - "xpack.ux.pageViews.analyze": "分析", "xpack.ux.percentile.50thMedian": "第 50 个(中值)", "xpack.ux.percentile.75th": "第 75 个", "xpack.ux.percentile.90th": "第 90 个", @@ -32091,4 +32048,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} +} \ No newline at end of file diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/empty_prompt.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/empty_prompt.tsx index c9f010b2d6a7e..1219ebe81ef25 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/empty_prompt.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/empty_prompt.tsx @@ -9,7 +9,13 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; -export const EmptyPrompt = ({ onCTAClicked }: { onCTAClicked: () => void }) => ( +export const EmptyPrompt = ({ + onCTAClicked, + showCreateRuleButton = true, +}: { + onCTAClicked: () => void; + showCreateRuleButton: boolean; +}) => ( void }) => (

    } actions={ - - - + showCreateRuleButton && ( + + + + ) } /> ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts index 74f6d9c2197b9..950d29c886f1a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts @@ -16,10 +16,10 @@ interface RuleTypesState { } interface RuleTypesProps { - filteredSolutions?: string[] | undefined; + filteredRuleTypes?: string[]; } -export function useLoadRuleTypes({ filteredSolutions }: RuleTypesProps) { +export function useLoadRuleTypes({ filteredRuleTypes }: RuleTypesProps) { const { http } = useKibana().services; const isMounted = useRef(false); const [ruleTypesState, setRuleTypesState] = useState({ @@ -42,8 +42,8 @@ export function useLoadRuleTypes({ filteredSolutions }: RuleTypesProps) { let filteredResponse = response; - if (filteredSolutions && filteredSolutions.length > 0) { - filteredResponse = response.filter((item) => filteredSolutions.includes(item.producer)); + if (filteredRuleTypes && filteredRuleTypes.length > 0) { + filteredResponse = response.filter((item) => filteredRuleTypes.includes(item.id)); } setRuleTypesState({ ...ruleTypesState, isLoading: false, data: filteredResponse }); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.ts index a309beeca58aa..d69f4b508dcf5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.test.ts @@ -375,4 +375,106 @@ describe('useLoadRules', () => { expect(onError).toBeCalled(); }); + + describe('No data', () => { + it('noData should be true, if there is no Filter and no rules', async () => { + loadRules.mockResolvedValue({ ...MOCK_RULE_DATA, data: [] }); + const params = { + page: { + index: 0, + size: 25, + }, + searchText: '', + typesFilter: [], + actionTypesFilter: [], + ruleExecutionStatusesFilter: [], + ruleStatusesFilter: [], + tagsFilter: [], + }; + + const { result, waitForNextUpdate } = renderHook(() => + useLoadRules({ + ...params, + onPage, + onError, + }) + ); + + expect(result.current.noData).toBeTruthy(); + + await act(async () => { + result.current.loadRules(); + await waitForNextUpdate(); + }); + + expect(result.current.noData).toBeTruthy(); + }); + + it('noData should be false, if there is rule types filter and no rules', async () => { + loadRules.mockResolvedValue({ ...MOCK_RULE_DATA, data: [] }); + const params = { + page: { + index: 0, + size: 25, + }, + searchText: '', + typesFilter: ['some-kind-of-filter'], + actionTypesFilter: [], + ruleExecutionStatusesFilter: [], + ruleStatusesFilter: [], + tagsFilter: [], + }; + + const { result, waitForNextUpdate } = renderHook(() => + useLoadRules({ + ...params, + onPage, + onError, + }) + ); + + expect(result.current.noData).toBeTruthy(); + + await act(async () => { + result.current.loadRules(); + await waitForNextUpdate(); + }); + + expect(result.current.noData).toBeFalsy(); + }); + + it('noData should be true, if there is rule types filter and no rules with hasDefaultRuleTypesFiltersOn = true', async () => { + loadRules.mockResolvedValue({ ...MOCK_RULE_DATA, data: [] }); + const params = { + page: { + index: 0, + size: 25, + }, + searchText: '', + typesFilter: ['some-kind-of-filter'], + actionTypesFilter: [], + ruleExecutionStatusesFilter: [], + ruleStatusesFilter: [], + tagsFilter: [], + hasDefaultRuleTypesFiltersOn: true, + }; + + const { result, waitForNextUpdate } = renderHook(() => + useLoadRules({ + ...params, + onPage, + onError, + }) + ); + + expect(result.current.noData).toBeTruthy(); + + await act(async () => { + result.current.loadRules(); + await waitForNextUpdate(); + }); + + expect(result.current.noData).toBeTruthy(); + }); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.ts index 4afdfd4f26a72..33cee4f2ffa88 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rules.ts @@ -18,6 +18,7 @@ interface RuleState { } type UseLoadRulesProps = Omit & { + hasDefaultRuleTypesFiltersOn?: boolean; onPage: (pagination: Pagination) => void; onError: (message: string) => void; }; @@ -92,6 +93,7 @@ export function useLoadRules({ sort, onPage, onError, + hasDefaultRuleTypesFiltersOn = false, }: UseLoadRulesProps) { const { http } = useKibana().services; const [state, dispatch] = useReducer(reducer, initialState); @@ -135,9 +137,10 @@ export function useLoadRules({ onPage({ ...page, index: 0 }); } + const hasEmptyTypesFilter = hasDefaultRuleTypesFiltersOn ? true : isEmpty(typesFilter); const isFilterApplied = !( isEmpty(searchText) && - isEmpty(typesFilter) && + hasEmptyTypesFilter && isEmpty(actionTypesFilter) && isEmpty(ruleExecutionStatusesFilter) && isEmpty(ruleStatusesFilter) && @@ -167,7 +170,7 @@ export function useLoadRules({ ruleStatusesFilter, tagsFilter, sort, - dispatch, + hasDefaultRuleTypesFiltersOn, onPage, onError, ]); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/rules_list_sandbox.tsx b/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/rules_list_sandbox.tsx index 0083811802955..f7bcb6f5390b9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/rules_list_sandbox.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/rules_list_sandbox.tsx @@ -18,6 +18,11 @@ export const RulesListSandbox = () => { } = useConnectorContext(); return ( -
    {getRulesListLazy({ connectorServices: { validateEmailAddresses } })}
    +
    + {getRulesListLazy({ + connectorServices: { validateEmailAddresses }, + rulesListProps: {}, + })} +
    ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.tsx index 7b74e414d200a..b9f8ae9f6b0ee 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_definition.tsx @@ -24,13 +24,12 @@ import { NOTIFY_WHEN_OPTIONS } from '../../rule_form/rule_notify_when'; import { RuleActions } from './rule_actions'; import { RuleEdit } from '../../rule_form'; -const OBSERVABILITY_SOLUTIONS = ['logs', 'uptime', 'infrastructure', 'apm']; - export const RuleDefinition: React.FunctionComponent = ({ rule, actionTypeRegistry, ruleTypeRegistry, onEditRule, + filteredRuleTypes, }) => { const { application: { capabilities }, @@ -39,7 +38,7 @@ export const RuleDefinition: React.FunctionComponent = ({ const [editFlyoutVisible, setEditFlyoutVisible] = useState(false); const [ruleType, setRuleType] = useState(); const { ruleTypes, ruleTypeIndex } = useLoadRuleTypes({ - filteredSolutions: OBSERVABILITY_SOLUTIONS, + filteredRuleTypes, }); const getRuleType = useMemo(() => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx index f89b3f91f150c..914d52de50299 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx @@ -48,7 +48,7 @@ const RuleAdd = ({ reloadRules, onSave, metadata, - filteredSolutions, + filteredRuleTypes, ...props }: RuleAddProps) => { const onSaveHandler = onSave ?? reloadRules; @@ -262,7 +262,7 @@ const RuleAdd = ({ actionTypeRegistry={actionTypeRegistry} ruleTypeRegistry={ruleTypeRegistry} metadata={metadata} - filteredSolutions={filteredSolutions} + filteredRuleTypes={filteredRuleTypes} /> > { setHasActionsDisabled?: (value: boolean) => void; setHasActionsWithBrokenConnector?: (value: boolean) => void; metadata?: MetaData; - filteredSolutions?: string[] | undefined; + filteredRuleTypes?: string[]; } export const RuleForm = ({ @@ -110,7 +110,7 @@ export const RuleForm = ({ ruleTypeRegistry, actionTypeRegistry, metadata, - filteredSolutions, + filteredRuleTypes: ruleTypeToFilter, }: RuleFormProps) => { const { notifications: { toasts }, @@ -163,7 +163,7 @@ export const RuleForm = ({ ruleTypes, error: loadRuleTypesError, ruleTypeIndex, - } = useLoadRuleTypes({ filteredSolutions }); + } = useLoadRuleTypes({ filteredRuleTypes: ruleTypeToFilter }); // load rule types useEffect(() => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.test.tsx new file mode 100644 index 0000000000000..d3ae27c5bd211 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.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 { mountWithIntl } from '@kbn/test-jest-helpers'; +import React from 'react'; +import { NumberField } from './number_field'; + +describe('NumberField', () => { + const onChange = jest.fn(); + + beforeEach(() => { + onChange.mockReset(); + }); + + test('allows any value with no defined min or max', () => { + const wrapper = mountWithIntl(); + wrapper + .find('input') + .first() + .simulate('change', { target: { value: 3 } }); + + expect(onChange).toHaveBeenCalledWith(3); + + wrapper + .find('input') + .first() + .simulate('change', { target: { value: 0 } }); + + expect(onChange).toHaveBeenCalledWith(0); + }); + + test('constrains value to defined min', () => { + const wrapper = mountWithIntl(); + wrapper + .find('input') + .first() + .simulate('change', { target: { value: 1 } }); + + expect(onChange).toHaveBeenCalledWith(1); + + wrapper + .find('input') + .first() + .simulate('change', { target: { value: -1 } }); + + expect(onChange).not.toHaveBeenCalledWith(-1); + }); + + test('constrains value to defined max', () => { + const wrapper = mountWithIntl(); + wrapper + .find('input') + .first() + .simulate('change', { target: { value: -1 } }); + + expect(onChange).toHaveBeenCalledWith(-1); + + wrapper + .find('input') + .first() + .simulate('change', { target: { value: 11 } }); + + expect(onChange).not.toHaveBeenCalledWith(11); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.tsx new file mode 100644 index 0000000000000..2483f6fc4a43c --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/helpers/number_field.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState, useCallback } from 'react'; +import { EuiFieldNumber, EuiFieldNumberProps } from '@elastic/eui'; + +export const NumberField: React.FC< + EuiFieldNumberProps & { + onChange: (value: string) => void; + } +> = (props) => { + const [displayValue, setDisplayValue] = useState(props.value); + const min = typeof props.min !== 'undefined' ? props.min : -Infinity; + const max = typeof props.max !== 'undefined' ? props.max : Infinity; + + const onChange = useCallback( + (e) => { + const { value } = e.target; + const isValid = !isNaN(Number(value)) && value >= min && value <= max; + if (isValid || value === '') { + setDisplayValue(value); + } + if (isValid && props.onChange) { + props.onChange(value); + } + }, + [props, setDisplayValue, max, min] + ); + + const onBlur = useCallback( + (e) => { + if (isNaN(Number(displayValue)) || displayValue === '') { + setDisplayValue(props.value); + } + if (props.onBlur) props.onBlur(e); + }, + [displayValue, props, setDisplayValue] + ); + + return ; +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/base_snooze_panel.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/base_snooze_panel.tsx index e1cf6aa3818fa..914ba3bb0cb05 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/base_snooze_panel.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/base_snooze_panel.tsx @@ -18,6 +18,7 @@ import { EuiIcon, EuiLink, EuiPopoverTitle, + EuiPopoverFooter, EuiSelect, EuiSpacer, EuiText, @@ -44,6 +45,7 @@ export interface BaseSnoozePanelProps { navigateToScheduler: (sched?: SnoozeSchedule) => void; isLoading: boolean; onRemoveAllSchedules: (ids: string[]) => void; + inPopover?: boolean; } export const BaseSnoozePanel: React.FunctionComponent = ({ @@ -56,6 +58,7 @@ export const BaseSnoozePanel: React.FunctionComponent = ({ navigateToScheduler, onRemoveAllSchedules, hasTitle, + inPopover = false, }) => { const [intervalValue, setIntervalValue] = useState(parseInterval(interval).value); const [intervalUnit, setIntervalUnit] = useState(parseInterval(interval).unit); @@ -132,6 +135,7 @@ export const BaseSnoozePanel: React.FunctionComponent = ({ = ({ )} - = ({ isLoading={isLoading} onClick={onClickApplyButton} data-test-subj="ruleSnoozeApply" + minWidth={0} > {i18n.translate('xpack.triggersActionsUI.sections.rulesList.applySnooze', { defaultMessage: 'Apply', @@ -239,12 +243,17 @@ export const BaseSnoozePanel: React.FunctionComponent = ({ - - + + {i18n.translate('xpack.triggersActionsUI.sections.rulesList.snoozeIndefinitely', { defaultMessage: 'Snooze indefinitely', })} - + @@ -253,6 +262,7 @@ export const BaseSnoozePanel: React.FunctionComponent = ({ = ({ )} {showCancel && ( <> - - - - - {i18n.translate('xpack.triggersActionsUI.sections.rulesList.cancelSnooze', { - defaultMessage: 'Cancel snooze', - })} - - - + {!inPopover && } + + {!inPopover && } + + + + {i18n.translate('xpack.triggersActionsUI.sections.rulesList.cancelSnooze', { + defaultMessage: 'Cancel snooze', + })} + + + + )} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/index.tsx index 7a5965532e4cf..7cd7829aec874 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/panel/index.tsx @@ -14,7 +14,13 @@ export { futureTimeToInterval } from './helpers'; type SnoozePanelProps = Pick< BaseSnoozePanelProps, - 'interval' | 'snoozeRule' | 'unsnoozeRule' | 'showCancel' | 'scheduledSnoozes' | 'hasTitle' + | 'interval' + | 'snoozeRule' + | 'unsnoozeRule' + | 'showCancel' + | 'scheduledSnoozes' + | 'hasTitle' + | 'inPopover' >; export const SnoozePanel: React.FC = ({ @@ -24,6 +30,7 @@ export const SnoozePanel: React.FC = ({ showCancel, scheduledSnoozes, hasTitle = true, + inPopover = false, }) => { const [isSchedulerOpen, setIsSchedulerOpen] = useState(false); const [initialSchedule, setInitialSchedule] = useState(null); @@ -98,6 +105,7 @@ export const SnoozePanel: React.FC = ({ navigateToScheduler={onOpenScheduler} onRemoveAllSchedules={cancelSnoozeSchedules} hasTitle={hasTitle} + inPopover={inPopover} /> ) : ( = ({ onSaveSchedule={saveSnoozeSchedule} onCancelSchedules={cancelSnoozeSchedules} hasTitle={hasTitle} + inPopover={inPopover} /> ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/custom_recurrence_scheduler.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/custom_recurrence_scheduler.tsx index e67717dc29161..b7568cfdc99db 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/custom_recurrence_scheduler.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/custom_recurrence_scheduler.tsx @@ -7,17 +7,18 @@ import { EuiButtonGroup, - EuiFieldNumber, - EuiFormControlLayoutDelimited, + EuiFormControlLayout, EuiFormRow, EuiSelect, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; import deepEqual from 'fast-deep-equal'; import { Moment } from 'moment'; import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react'; +import { NumberField } from '../helpers/number_field'; import { RRuleFrequency } from '../../../../../../types'; import { I18N_WEEKDAY_OPTIONS } from './constants'; import { @@ -28,13 +29,6 @@ import { } from './helpers'; import { i18nEndControlOptions, i18nNthWeekdayShort } from './translations'; -// FIXME https://github.com/elastic/eui/issues/5958 -const EuiFormRowWithDelimitedFixer = euiStyled(EuiFormRow)` - & .euiFormControlLayout__childrenWrapper { - height: 100%; - } -`; - interface CustomRecurrenceSchedulerProps { startDate: Moment | null; onChange: (state: CustomFrequencyState) => void; @@ -66,7 +60,7 @@ export const CustomRecurrenceScheduler: React.FC const monthlyRecurDayOptions = useMemo(() => { if (!startDate) return []; - const { dayOfWeek, nthWeekdayOfMonth, isLastOfMonth } = getWeekdayInfo(startDate); + const { dayOfWeek, nthWeekdayOfMonth, isLastOfMonth } = getWeekdayInfo(startDate, 'ddd'); return [ { id: 'day', @@ -129,49 +123,49 @@ export const CustomRecurrenceScheduler: React.FC return ( <> - - setInterval(Number(e.target.value))} - /> - } - endControl={ + + + + setInterval(Number(value))} + /> + + + setFrequency(Number(e.target.value))} value={frequency} options={endControlOptions} /> - } - /> - + + + {frequency === RRuleFrequency.WEEKLY && ( )} {frequency === RRuleFrequency.MONTHLY && startDate && ( - + { - const dayOfWeek = date.format('dddd'); +export const getWeekdayInfo = (date: Moment, dayOfWeekFmt: string = 'dddd') => { + const dayOfWeek = date.format(dayOfWeekFmt); const nthWeekdayOfMonth = Math.ceil(date.date() / 7); const isLastOfMonth = nthWeekdayOfMonth > 4 || !date.isSame(moment(date).add(7, 'd'), 'month'); return { dayOfWeek, nthWeekdayOfMonth, isLastOfMonth }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/index.tsx index 6b98dd34984e2..4220e287c5f17 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/index.tsx @@ -8,12 +8,11 @@ import { EuiButtonGroup, EuiDatePicker, - EuiFieldNumber, EuiFormControlLayout, EuiFormRow, EuiHorizontalRule, - EuiPanel, EuiSelect, + EuiSplitPanel, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import moment from 'moment'; @@ -21,6 +20,7 @@ import { Moment } from 'moment'; import React from 'react'; import { useEffect, useMemo, useRef, useState } from 'react'; +import { NumberField } from '../helpers/number_field'; import { RRuleFrequency, RecurrenceSchedule } from '../../../../../../types'; import { i18nMonthDayDate } from '../../../../../lib/i18n_month_day_date'; import { @@ -38,6 +38,8 @@ import { } from './helpers'; import { i18nNthWeekday } from './translations'; +import './recurrence_scheduler.scss'; + interface ComponentOpts { startDate: Moment | null; endDate: Moment | null; @@ -192,8 +194,8 @@ export const RecurrenceScheduler: React.FC = ({ }, [compiledRecurrenceSchedule, onChange]); return ( - -
    + + = ({ } )} > - setOccurrrences(Number(e.target.value))} + onChange={(value) => setOccurrrences(Number(value))} /> )} -
    + -
    + {i18n.translate('xpack.triggersActionsUI.ruleSnoozeScheduler.repeatsSummary', { defaultMessage: 'Repeats {summary}', values: { summary: recurrenceSummary(compiledRecurrenceSchedule) }, })} -
    -
    + + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/recurrence_scheduler.scss b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/recurrence_scheduler.scss new file mode 100644 index 0000000000000..eb820e07f55fc --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/recurrence_scheduler/recurrence_scheduler.scss @@ -0,0 +1,8 @@ +.ramRecurrenceScheduler { + .euiFormRow__labelWrapper { + width: calc(20% - 8px); + } + .euiFormRow__fieldWrapper { + width: 80%; + } +} \ No newline at end of file diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/scheduler.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/scheduler.tsx index 8fcdf10da9567..ee4721d15b289 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/scheduler.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze/scheduler.tsx @@ -13,7 +13,6 @@ import uuid from 'uuid'; import { EuiDatePicker, EuiDatePickerRange, - EuiPanel, EuiComboBox, EuiFormRow, EuiHorizontalRule, @@ -23,8 +22,10 @@ import { EuiSpacer, EuiButton, EuiPopoverTitle, + EuiPopoverFooter, EuiIcon, EuiLink, + EuiSplitPanel, } from '@elastic/eui'; import { RecurrenceSchedule, SnoozeSchedule } from '../../../../../types'; import { RecurrenceScheduler } from './recurrence_scheduler'; @@ -36,6 +37,7 @@ interface PanelOpts { onCancelSchedules: (ids: string[]) => void; initialSchedule: SnoozeSchedule | null; isLoading: boolean; + inPopover?: boolean; } export interface ComponentOpts extends PanelOpts { @@ -93,6 +95,7 @@ const RuleSnoozeSchedulerPanel: React.FunctionComponent = ({ initialSchedule, isLoading, onCancelSchedules, + inPopover = false, }) => { // These two states form a state machine for whether or not the user's clicks on the datepicker apply to the start/end date or start/end time // - State A: After the user clicks a start date: @@ -111,7 +114,9 @@ const RuleSnoozeSchedulerPanel: React.FunctionComponent = ({ const [selectingEndDate, setSelectingEndDate] = useState(false); const [selectingEndTime, setSelectingEndTime] = useState(false); const minDate = useMemo( - () => moment(initialSchedule?.rRule.dtstart ?? undefined), + // If the initial schedule is earlier than now, set minDate to it + // Set minDate to now if the initial schedule is in the future + () => moment.min(moment(), moment(initialSchedule?.rRule.dtstart ?? undefined)), [initialSchedule] ); @@ -240,7 +245,7 @@ const RuleSnoozeSchedulerPanel: React.FunctionComponent = ({ }, [initialSchedule, onCancelSchedules]); return ( - + <> = ({ /> - - + + = ({ minDate={minDate} adjustDateOnChange={false} /> - + - + = ({ isClearable={false} /> - - + + @@ -325,7 +325,7 @@ const RuleSnoozeSchedulerPanel: React.FunctionComponent = ({ /> {isRecurring && ( <> - + = ({ {initialSchedule && ( <> - - - - - {i18n.translate('xpack.triggersActionsUI.sections.rulesList.deleteSchedule', { - defaultMessage: 'Delete schedule', - })} - - - + {!inPopover && } + + {!inPopover && } + + + + {i18n.translate('xpack.triggersActionsUI.sections.rulesList.deleteSchedule', { + defaultMessage: 'Delete schedule', + })} + + + + )} - + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx index 88e6006a601e7..e2054ab13cb4c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx @@ -466,6 +466,562 @@ describe.skip('rules_list component empty', () => { }); }); +describe('rules_list component with props', () => { + describe('Status filter', () => { + let wrapper: ReactWrapper; + async function setup(editable: boolean = true) { + loadRules.mockResolvedValue({ + page: 1, + perPage: 10000, + total: 4, + data: mockedRulesData, + }); + loadActionTypes.mockResolvedValue([ + { + id: 'test', + name: 'Test', + }, + { + id: 'test2', + name: 'Test2', + }, + ]); + loadRuleTypes.mockResolvedValue([ruleTypeFromApi]); + loadAllActions.mockResolvedValue([]); + loadRuleAggregations.mockResolvedValue({ + ruleEnabledStatus: { enabled: 2, disabled: 0 }, + ruleExecutionStatus: { ok: 1, active: 2, error: 3, pending: 4, unknown: 5, warning: 6 }, + ruleMutedStatus: { muted: 0, unmuted: 2 }, + ruleTags, + }); + loadRuleTags.mockResolvedValue({ + ruleTags, + }); + + const ruleTypeMock: RuleTypeModel = { + id: 'test_rule_type', + iconClass: 'test', + description: 'Rule when testing', + documentationUrl: 'https://localhost.local/docs', + validate: () => { + return { errors: {} }; + }, + ruleParamsExpression: jest.fn(), + requiresAppContext: !editable, + }; + + ruleTypeRegistry.has.mockReturnValue(true); + ruleTypeRegistry.get.mockReturnValue(ruleTypeMock); + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; + + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; + wrapper = mountWithIntl( + + ); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(loadRules).toHaveBeenCalled(); + expect(loadActionTypes).toHaveBeenCalled(); + expect(loadRuleAggregations).toHaveBeenCalled(); + } + it('can filter by rule states', async () => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => true); + loadRules.mockReset(); + await setup(); + + expect(loadRules).toHaveBeenLastCalledWith( + expect.objectContaining({ + ruleStatusesFilter: ['disabled'], + }) + ); + + wrapper.find('[data-test-subj="ruleStatusFilterButton"] button').simulate('click'); + + wrapper.find('[data-test-subj="ruleStatusFilterOption-enabled"]').first().simulate('click'); + + expect(loadRules).toHaveBeenLastCalledWith( + expect.objectContaining({ + ruleStatusesFilter: ['disabled', 'enabled'], + }) + ); + + expect(wrapper.prop('onStatusFilterChange')).toHaveBeenCalled(); + expect(wrapper.prop('onStatusFilterChange')).toHaveBeenLastCalledWith([ + 'disabled', + 'enabled', + ]); + }); + }); + + describe('Last response filter', () => { + let wrapper: ReactWrapper; + async function setup(editable: boolean = true) { + loadRules.mockResolvedValue({ + page: 1, + perPage: 10000, + total: 4, + data: mockedRulesData, + }); + loadActionTypes.mockResolvedValue([ + { + id: 'test', + name: 'Test', + }, + { + id: 'test2', + name: 'Test2', + }, + ]); + loadRuleTypes.mockResolvedValue([ruleTypeFromApi]); + loadAllActions.mockResolvedValue([]); + loadRuleAggregations.mockResolvedValue({ + ruleEnabledStatus: { enabled: 2, disabled: 0 }, + ruleExecutionStatus: { ok: 1, active: 2, error: 3, pending: 4, unknown: 5, warning: 6 }, + ruleMutedStatus: { muted: 0, unmuted: 2 }, + ruleTags, + }); + loadRuleTags.mockResolvedValue({ + ruleTags, + }); + + const ruleTypeMock: RuleTypeModel = { + id: 'test_rule_type', + iconClass: 'test', + description: 'Rule when testing', + documentationUrl: 'https://localhost.local/docs', + validate: () => { + return { errors: {} }; + }, + ruleParamsExpression: jest.fn(), + requiresAppContext: !editable, + }; + + ruleTypeRegistry.has.mockReturnValue(true); + ruleTypeRegistry.get.mockReturnValue(ruleTypeMock); + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; + + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; + wrapper = mountWithIntl( + + ); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(loadRules).toHaveBeenCalled(); + expect(loadActionTypes).toHaveBeenCalled(); + expect(loadRuleAggregations).toHaveBeenCalled(); + } + it('can filter by last response', async () => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => true); + loadRules.mockReset(); + await setup(); + + expect(loadRules).toHaveBeenLastCalledWith( + expect.objectContaining({ + ruleExecutionStatusesFilter: ['error'], + }) + ); + + wrapper.find('[data-test-subj="ruleExecutionStatusFilterButton"] button').simulate('click'); + + wrapper + .find('[data-test-subj="ruleExecutionStatusactiveFilterOption"]') + .first() + .simulate('click'); + + expect(loadRules).toHaveBeenLastCalledWith( + expect.objectContaining({ + ruleExecutionStatusesFilter: ['error', 'active'], + }) + ); + + expect(wrapper.prop('onLastResponseFilterChange')).toHaveBeenCalled(); + expect(wrapper.prop('onLastResponseFilterChange')).toHaveBeenLastCalledWith([ + 'error', + 'active', + ]); + + wrapper.find('[data-test-subj="ruleExecutionStatusFilterButton"] button').simulate('click'); + wrapper + .find('[data-test-subj="ruleExecutionStatuserrorFilterOption"]') + .first() + .simulate('click'); + + expect(loadRules).toHaveBeenLastCalledWith( + expect.objectContaining({ + ruleExecutionStatusesFilter: ['active'], + }) + ); + + expect(wrapper.prop('onLastResponseFilterChange')).toHaveBeenCalled(); + expect(wrapper.prop('onLastResponseFilterChange')).toHaveBeenLastCalledWith(['active']); + }); + }); + + describe('showActionFilter prop', () => { + let wrapper: ReactWrapper; + async function setup(editable: boolean = true) { + loadRules.mockResolvedValue({ + page: 1, + perPage: 10000, + total: 4, + data: mockedRulesData, + }); + loadActionTypes.mockResolvedValue([ + { + id: 'test', + name: 'Test', + }, + { + id: 'test2', + name: 'Test2', + }, + ]); + loadRuleTypes.mockResolvedValue([ruleTypeFromApi]); + loadAllActions.mockResolvedValue([]); + loadRuleAggregations.mockResolvedValue({ + ruleEnabledStatus: { enabled: 2, disabled: 0 }, + ruleExecutionStatus: { ok: 1, active: 2, error: 3, pending: 4, unknown: 5, warning: 6 }, + ruleMutedStatus: { muted: 0, unmuted: 2 }, + ruleTags, + }); + loadRuleTags.mockResolvedValue({ + ruleTags, + }); + + const ruleTypeMock: RuleTypeModel = { + id: 'test_rule_type', + iconClass: 'test', + description: 'Rule when testing', + documentationUrl: 'https://localhost.local/docs', + validate: () => { + return { errors: {} }; + }, + ruleParamsExpression: jest.fn(), + requiresAppContext: !editable, + }; + + ruleTypeRegistry.has.mockReturnValue(true); + ruleTypeRegistry.get.mockReturnValue(ruleTypeMock); + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; + + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; + } + it('hides the ActionFilter component', async () => { + wrapper = mountWithIntl(); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(loadRules).toHaveBeenCalled(); + expect(loadActionTypes).toHaveBeenCalled(); + expect(loadRuleAggregations).toHaveBeenCalled(); + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => true); + loadRules.mockReset(); + await setup(); + expect(wrapper.find('ActionTypeFilter')).toHaveLength(0); + }); + + it('shows the ActionFilter component if no prop is passed', async () => { + wrapper = mountWithIntl(); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(loadRules).toHaveBeenCalled(); + expect(loadActionTypes).toHaveBeenCalled(); + expect(loadRuleAggregations).toHaveBeenCalled(); + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => true); + loadRules.mockReset(); + await setup(); + expect(wrapper.find('ActionTypeFilter')).toHaveLength(1); + }); + }); + + describe('showCreateRuleButton prop', () => { + let wrapper: ReactWrapper; + async function setup(editable: boolean = true) { + loadRules.mockResolvedValue({ + page: 1, + perPage: 10000, + total: 4, + data: mockedRulesData, + }); + loadActionTypes.mockResolvedValue([ + { + id: 'test', + name: 'Test', + }, + { + id: 'test2', + name: 'Test2', + }, + ]); + loadRuleTypes.mockResolvedValue([ruleTypeFromApi]); + loadAllActions.mockResolvedValue([]); + loadRuleAggregations.mockResolvedValue({ + ruleEnabledStatus: { enabled: 2, disabled: 0 }, + ruleExecutionStatus: { ok: 1, active: 2, error: 3, pending: 4, unknown: 5, warning: 6 }, + ruleMutedStatus: { muted: 0, unmuted: 2 }, + ruleTags, + }); + loadRuleTags.mockResolvedValue({ + ruleTags, + }); + + const ruleTypeMock: RuleTypeModel = { + id: 'test_rule_type', + iconClass: 'test', + description: 'Rule when testing', + documentationUrl: 'https://localhost.local/docs', + validate: () => { + return { errors: {} }; + }, + ruleParamsExpression: jest.fn(), + requiresAppContext: !editable, + }; + + ruleTypeRegistry.has.mockReturnValue(true); + ruleTypeRegistry.get.mockReturnValue(ruleTypeMock); + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; + + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; + } + + it('hides the Create Rule button', async () => { + wrapper = mountWithIntl(); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => true); + loadRules.mockReset(); + await setup(); + expect(wrapper.find('EuiButton[data-test-subj="createRuleButton"]').length).toEqual(0); + }); + + it('shows the Create Rule button by default', async () => { + wrapper = mountWithIntl(); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => true); + loadRules.mockReset(); + await setup(); + expect(wrapper.find('EuiButton[data-test-subj="createRuleButton"]').length).toEqual(1); + }); + }); + + describe('filteredRuleTypes prop', () => { + let wrapper: ReactWrapper; + const allRulesData = [ + { + id: '1', + name: 'test rule', + tags: ['tag1'], + enabled: true, + ruleTypeId: 'test_rule_type', + schedule: { interval: '1s' }, + actions: [], + params: { name: 'test rule type name' }, + scheduledTaskId: null, + createdBy: null, + updatedBy: null, + apiKeyOwner: null, + throttle: '1m', + muteAll: false, + mutedInstanceIds: [], + executionStatus: { + status: 'active', + lastDuration: 500, + lastExecutionDate: new Date('2020-08-20T19:23:38Z'), + error: null, + }, + monitoring: { + execution: { + history: [ + { + success: true, + duration: 1000000, + }, + { + success: true, + duration: 200000, + }, + { + success: false, + duration: 300000, + }, + ], + calculated_metrics: { + success_ratio: 0.66, + p50: 200000, + p95: 300000, + p99: 300000, + }, + }, + }, + }, + { + id: '2', + name: 'test rule ok', + tags: ['tag1'], + enabled: true, + ruleTypeId: 'test_rule_type2', + schedule: { interval: '5d' }, + actions: [], + params: { name: 'test rule type name' }, + scheduledTaskId: null, + createdBy: null, + updatedBy: null, + apiKeyOwner: null, + throttle: '1m', + muteAll: false, + mutedInstanceIds: [], + executionStatus: { + status: 'ok', + lastDuration: 61000, + lastExecutionDate: new Date('2020-08-20T19:23:38Z'), + error: null, + }, + monitoring: { + execution: { + history: [ + { + success: true, + duration: 100000, + }, + { + success: true, + duration: 500000, + }, + ], + calculated_metrics: { + success_ratio: 1, + p50: 0, + p95: 100000, + p99: 500000, + }, + }, + }, + }, + { + id: '3', + name: 'test rule pending', + tags: ['tag1'], + enabled: true, + ruleTypeId: 'test_rule_type2', + schedule: { interval: '5d' }, + actions: [], + params: { name: 'test rule type name' }, + scheduledTaskId: null, + createdBy: null, + updatedBy: null, + apiKeyOwner: null, + throttle: '1m', + muteAll: false, + mutedInstanceIds: [], + executionStatus: { + status: 'pending', + lastDuration: 30234, + lastExecutionDate: new Date('2020-08-20T19:23:38Z'), + error: null, + }, + monitoring: { + execution: { + history: [{ success: false, duration: 100 }], + calculated_metrics: { + success_ratio: 0, + }, + }, + }, + }, + ]; + async function setup(editable: boolean = true, filteredRuleTypes: string[]) { + loadRules.mockResolvedValue({ + page: 1, + perPage: 10000, + total: 2, + data: allRulesData.filter(({ ruleTypeId }) => filteredRuleTypes.includes(ruleTypeId)), + }); + + loadActionTypes.mockResolvedValue([ + { + id: 'test', + name: 'Test', + }, + { + id: 'test2', + name: 'Test2', + }, + ]); + loadRuleTypes.mockResolvedValue([ + ruleTypeFromApi, + { ...ruleTypeFromApi, id: 'test_rule_type2' }, + ]); + loadAllActions.mockResolvedValue([]); + loadRuleAggregations.mockResolvedValue({ + ruleEnabledStatus: { enabled: 2, disabled: 0 }, + ruleExecutionStatus: { ok: 1, active: 2, error: 3, pending: 4, unknown: 5, warning: 6 }, + ruleMutedStatus: { muted: 0, unmuted: 2 }, + ruleTags, + }); + loadRuleTags.mockResolvedValue({ + ruleTags, + }); + + const ruleTypeMock: RuleTypeModel = { + id: 'test_rule_type', + iconClass: 'test', + description: 'Rule when testing', + documentationUrl: 'https://localhost.local/docs', + validate: () => { + return { errors: {} }; + }, + ruleParamsExpression: jest.fn(), + requiresAppContext: !editable, + }; + + ruleTypeRegistry.has.mockReturnValue(true); + ruleTypeRegistry.get.mockReturnValue(ruleTypeMock); + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.ruleTypeRegistry = ruleTypeRegistry; + + // eslint-disable-next-line react-hooks/rules-of-hooks + useKibanaMock().services.actionTypeRegistry = actionTypeRegistry; + + wrapper = mountWithIntl(); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + } + + it('renders only rules for the specified rule types', async () => { + const filteredRuleTypes = ['test_rule_type2']; + await setup(true, filteredRuleTypes); + expect(wrapper.find('EuiTableRow')).not.toHaveLength(allRulesData.length); + expect(wrapper.find('EuiTableRow')).toHaveLength(2); + }); + }); +}); + describe('rules_list component with items', () => { let wrapper: ReactWrapper; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index 91fac39f1d345..942e280359406 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import moment from 'moment'; -import { capitalize, sortBy } from 'lodash'; +import { capitalize, isEmpty, sortBy } from 'lodash'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { useEffect, useState, ReactNode, useCallback, useMemo } from 'react'; import { @@ -87,9 +87,29 @@ import { useLoadRuleAggregations } from '../../../hooks/use_load_rule_aggregatio import { RulesListTable, convertRulesToTableItems } from './rules_list_table'; import { RulesListAutoRefresh } from './rules_list_auto_refresh'; import { UpdateApiKeyModalConfirmation } from '../../../components/update_api_key_modal_confirmation'; +import { RulesListVisibleColumns } from './rules_list_column_selector'; const ENTER_KEY = 13; +interface RulesPageContainerState { + lastResponse: string[]; + status: RuleStatus[]; +} + +export interface RulesListProps { + filteredRuleTypes?: string[]; + showActionFilter?: boolean; + ruleDetailsRoute?: string; + showCreateRuleButton?: boolean; + statusFilter?: RuleStatus[]; + onStatusFilterChange?: (status: RuleStatus[]) => RulesPageContainerState; + lastResponseFilter?: string[]; + onLastResponseFilterChange?: (lastResponse: string[]) => RulesPageContainerState; + refresh?: Date; + rulesListKey?: string; + visibleColumns?: RulesListVisibleColumns[]; +} + interface RuleTypeState { isLoading: boolean; isInitialized: boolean; @@ -108,7 +128,19 @@ const initialPercentileOptions = Object.values(Percentiles).map((percentile) => key: percentile, })); -export const RulesList: React.FunctionComponent = () => { +export const RulesList = ({ + filteredRuleTypes = [], + showActionFilter = true, + ruleDetailsRoute, + showCreateRuleButton = true, + statusFilter, + onStatusFilterChange, + lastResponseFilter, + onLastResponseFilterChange, + refresh, + rulesListKey, + visibleColumns, +}: RulesListProps) => { const history = useHistory(); const { http, @@ -127,10 +159,13 @@ export const RulesList: React.FunctionComponent = () => { const [page, setPage] = useState({ index: 0, size: DEFAULT_SEARCH_PAGE_SIZE }); const [searchText, setSearchText] = useState(); const [inputText, setInputText] = useState(); - const [typesFilter, setTypesFilter] = useState([]); + const [typesFilter, setTypesFilter] = useState(); const [actionTypesFilter, setActionTypesFilter] = useState([]); - const [ruleExecutionStatusesFilter, setRuleExecutionStatusesFilter] = useState([]); - const [ruleStatusesFilter, setRuleStatusesFilter] = useState([]); + const [ruleExecutionStatusesFilter, setRuleExecutionStatusesFilter] = useState( + lastResponseFilter || [] + ); + const [ruleStatusesFilter, setRuleStatusesFilter] = useState(statusFilter || []); + const [tagsFilter, setTagsFilter] = useState([]); const [ruleFlyoutVisible, setRuleFlyoutVisibility] = useState(false); const [editFlyoutVisible, setEditFlyoutVisibility] = useState(false); @@ -180,10 +215,22 @@ export const RulesList: React.FunctionComponent = () => { [toasts] ); + const authorizedRuleTypes = useMemo(() => [...ruleTypesState.data.values()], [ruleTypesState]); + const authorizedToCreateAnyRules = authorizedRuleTypes.some( + (ruleType) => ruleType.authorizedConsumers[ALERTS_FEATURE_ID]?.all + ); + + const [rulesTypesFilter, hasDefaultRuleTypesFiltersOn] = useMemo(() => { + if (isEmpty(typesFilter) && !isEmpty(filteredRuleTypes)) { + return [authorizedRuleTypes.map((art) => art.id), true]; + } + return [typesFilter, false]; + }, [typesFilter, filteredRuleTypes, authorizedRuleTypes]); + const { rulesState, setRulesState, loadRules, noData, initialLoad } = useLoadRules({ page, searchText, - typesFilter, + typesFilter: rulesTypesFilter, actionTypesFilter, ruleExecutionStatusesFilter, ruleStatusesFilter, @@ -191,6 +238,7 @@ export const RulesList: React.FunctionComponent = () => { sort, onPage: setPage, onError, + hasDefaultRuleTypesFiltersOn, }); const { tags, loadTags } = useLoadTags({ @@ -236,6 +284,10 @@ export const RulesList: React.FunctionComponent = () => { ruleTypesState, ]); + useEffect(() => { + loadData(); + }, [loadData, refresh]); + useEffect(() => { loadData(); }, [loadData, percentileOptions]); @@ -249,7 +301,15 @@ export const RulesList: React.FunctionComponent = () => { for (const ruleType of ruleTypes) { index.set(ruleType.id, ruleType); } - setRuleTypesState({ isLoading: false, data: index, isInitialized: true }); + let filteredIndex = index; + if (filteredRuleTypes && filteredRuleTypes.length > 0) { + filteredIndex = new Map( + [...index].filter(([k, v]) => { + return filteredRuleTypes.includes(v.id); + }) + ); + } + setRuleTypesState({ isLoading: false, data: filteredIndex, isInitialized: true }); } catch (e) { toasts.addDanger({ title: i18n.translate( @@ -285,6 +345,30 @@ export const RulesList: React.FunctionComponent = () => { })(); }, []); + useEffect(() => { + if (onStatusFilterChange) { + onStatusFilterChange(ruleStatusesFilter); + } + }, [ruleStatusesFilter]); + + useEffect(() => { + if (statusFilter) { + setRuleStatusesFilter(statusFilter); + } + }, [statusFilter]); + + useEffect(() => { + if (lastResponseFilter) { + setRuleExecutionStatusesFilter(lastResponseFilter); + } + }, [lastResponseFilter]); + + useEffect(() => { + if (onLastResponseFilterChange) { + onLastResponseFilterChange(ruleExecutionStatusesFilter); + } + }, [ruleExecutionStatusesFilter]); + const buildErrorListItems = (_executionStatus: RuleExecutionStatus) => { const hasErrorMessage = _executionStatus.status === 'error'; const errorMessage = _executionStatus?.error?.message; @@ -347,11 +431,6 @@ export const RulesList: React.FunctionComponent = () => { }); }, [showErrors, rulesState]); - const authorizedRuleTypes = [...ruleTypesState.data.values()]; - const authorizedToCreateAnyRules = authorizedRuleTypes.some( - (ruleType) => ruleType.authorizedConsumers[ALERTS_FEATURE_ID]?.all - ); - const getProducerFeatureName = (producer: string) => { return kibanaFeatures?.find((featureItem) => featureItem.id === producer)?.name; }; @@ -413,26 +492,30 @@ export const RulesList: React.FunctionComponent = () => { return unsnoozeRule({ http, id: rule.id, scheduleIds }); }; + const filterOptions = sortBy(Object.entries(groupRuleTypesByProducer())).map( + ([groupName, ruleTypesOptions]) => ({ + groupName: getProducerFeatureName(groupName) ?? capitalize(groupName), + subOptions: ruleTypesOptions.sort((a, b) => a.name.localeCompare(b.name)), + }) + ); + const toolsRight = [ setTypesFilter(types)} - options={sortBy(Object.entries(groupRuleTypesByProducer())).map( - ([groupName, ruleTypesOptions]) => ({ - groupName: getProducerFeatureName(groupName) ?? capitalize(groupName), - subOptions: ruleTypesOptions.sort((a, b) => a.name.localeCompare(b.name)), - }) - )} - />, - setActionTypesFilter(ids)} + options={filterOptions} />, + showActionFilter && ( + setActionTypesFilter(ids)} + /> + ), setRuleExecutionStatusesFilter(ids)} + onChange={setRuleExecutionStatusesFilter} />, ...getRuleTagFilter(), ]; @@ -494,7 +577,7 @@ export const RulesList: React.FunctionComponent = () => {
    )} - {authorizedToCreateAnyRules ? ( + {authorizedToCreateAnyRules && showCreateRuleButton ? ( { ))} + + + + +
    @@ -661,7 +758,8 @@ export const RulesList: React.FunctionComponent = () => { onPage={setPage} onRuleChanged={() => loadData()} onRuleClick={(rule) => { - history.push(routeToRuleDetails.replace(`:ruleId`, rule.id)); + const detailsRoute = ruleDetailsRoute ? ruleDetailsRoute : routeToRuleDetails; + history.push(detailsRoute.replace(`:ruleId`, rule.id)); }} onRuleEditClick={(rule) => { if (rule.isEditable && isRuleTypeEditableInContext(rule.ruleTypeId)) { @@ -708,7 +806,9 @@ export const RulesList: React.FunctionComponent = () => { /> ) : null; }} + rulesListKey={rulesListKey} config={config} + visibleColumns={visibleColumns} /> {manageLicenseModalOpts && ( { )} ); - // if initial load, show spinner const getRulesList = () => { if (noData && !rulesState.isLoading && !ruleTypesState.isLoading) { return authorizedToCreateAnyRules ? ( - setRuleFlyoutVisibility(true)} /> + setRuleFlyoutVisibility(true)} + /> ) : ( noPermissionPrompt ); @@ -820,6 +922,7 @@ export { RulesList as default }; const noPermissionPrompt = ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_notify_badge.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_notify_badge.tsx index 1bacc0003150c..2aaaa0af1123a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_notify_badge.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_notify_badge.tsx @@ -314,6 +314,7 @@ export const RulesListNotifyBadge: React.FunctionComponent ); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/common/get_rules_list.tsx index dd112d46b48a2..82b266d738203 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/get_rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_rules_list.tsx @@ -8,12 +8,16 @@ import React from 'react'; import { ConnectorProvider } from '../application/context/connector_context'; import { RulesList } from '../application/sections'; +import type { RulesListProps } from '../application/sections/rules_list/components/rules_list'; import { ConnectorServices } from '../types'; -export const getRulesListLazy = (props: { connectorServices: ConnectorServices }) => { +export const getRulesListLazy = (props: { + connectorServices: ConnectorServices; + rulesListProps: RulesListProps; +}) => { return ( - + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/index.ts b/x-pack/plugins/triggers_actions_ui/public/index.ts index 524903aa125ad..47a0d7b98167b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/index.ts @@ -15,7 +15,6 @@ export type { RuleAction, Rule, RuleType, - RuleTypeIndex, RuleTypeModel, RuleStatus, ActionType, @@ -29,7 +28,6 @@ export type { RuleFlyoutCloseReason, RuleTypeParams, AsApiContract, - RuleTableItem, AlertsTableProps, BulkActionsObjectProp, RuleSummary, @@ -42,6 +40,7 @@ export type { FieldBrowserOptions, FieldBrowserProps, RuleDefinitionProps, + RulesListVisibleColumns, } from './types'; export { diff --git a/x-pack/plugins/triggers_actions_ui/public/mocks.ts b/x-pack/plugins/triggers_actions_ui/public/mocks.ts index 31c4acc22808a..4e74d2772ad40 100644 --- a/x-pack/plugins/triggers_actions_ui/public/mocks.ts +++ b/x-pack/plugins/triggers_actions_ui/public/mocks.ts @@ -109,7 +109,10 @@ function createStartMock(): TriggersAndActionsUIPublicPluginStart { return getRulesListNotifyBadgeLazy(props); }, getRulesList: () => { - return getRulesListLazy({ connectorServices }); + return getRulesListLazy({ + connectorServices, + rulesListProps: {}, + }); }, getRuleDefinition: (props) => { return getRuleDefinitionLazy({ ...props, actionTypeRegistry, ruleTypeRegistry }); diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index 778dd0dc20dcd..a70802119fb6d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -59,6 +59,7 @@ import type { RuleTagBadgeProps, RuleTagBadgeOptions, RuleEventLogListProps, + RulesListProps, RulesListNotifyBadgeProps, AlertsTableConfigurationRegistry, CreateConnectorFlyoutProps, @@ -111,10 +112,10 @@ export interface TriggersAndActionsUIPublicPluginStart { props: RuleTagBadgeProps ) => ReactElement>; getRuleEventLogList: (props: RuleEventLogListProps) => ReactElement; + getRulesList: (props: RulesListProps) => ReactElement; getRulesListNotifyBadge: ( props: RulesListNotifyBadgeProps ) => ReactElement; - getRulesList: () => ReactElement; getRuleDefinition: (props: RuleDefinitionProps) => ReactElement; getRuleStatusPanel: (props: RuleStatusPanelProps) => ReactElement; } @@ -332,8 +333,11 @@ export class Plugin getRulesListNotifyBadge: (props: RulesListNotifyBadgeProps) => { return getRulesListNotifyBadgeLazy(props); }, - getRulesList: () => { - return getRulesListLazy({ connectorServices: this.connectorServices! }); + getRulesList: (props: RulesListProps) => { + return getRulesListLazy({ + connectorServices: this.connectorServices!, + rulesListProps: props, + }); }, getRuleDefinition: ( props: Omit diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index 9f407d8ebe359..d24d658f90d10 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -50,6 +50,7 @@ import { TypeRegistry } from './application/type_registry'; import type { ComponentOpts as RuleStatusDropdownProps } from './application/sections/rules_list/components/rule_status_dropdown'; import type { RuleTagFilterProps } from './application/sections/rules_list/components/rule_tag_filter'; import type { RuleStatusFilterProps } from './application/sections/rules_list/components/rule_status_filter'; +import type { RulesListProps } from './application/sections/rules_list/components/rules_list'; import type { RuleTagBadgeProps, RuleTagBadgeOptions, @@ -65,6 +66,7 @@ import type { FieldBrowserProps, BrowserFieldItem, } from './application/sections/field_browser/types'; +import { RulesListVisibleColumns } from './application/sections/rules_list/components/rules_list_column_selector'; // In Triggers and Actions we treat all `Alert`s as `SanitizedRule` // so the `Params` is a black-box of Record @@ -102,6 +104,7 @@ export type { RuleTagBadgeProps, RuleTagBadgeOptions, RuleEventLogListProps, + RulesListProps, CreateConnectorFlyoutProps, EditConnectorFlyoutProps, RulesListNotifyBadgeProps, @@ -110,6 +113,7 @@ export type { CreateFieldComponent, GetFieldTableColumns, BrowserFieldItem, + RulesListVisibleColumns, }; export type { ActionType, AsApiContract }; export { @@ -353,13 +357,14 @@ export interface RuleAddProps> { onSave?: () => Promise; metadata?: MetaData; ruleTypeIndex?: RuleTypeIndex; - filteredSolutions?: string[] | undefined; + filteredRuleTypes?: string[]; } export interface RuleDefinitionProps { rule: Rule; ruleTypeRegistry: RuleTypeRegistryContract; actionTypeRegistry: ActionTypeRegistryContract; onEditRule: () => Promise; + filteredRuleTypes?: string[]; } export enum Percentiles { diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/page_load_dist_chart.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/page_load_dist_chart.tsx index 7d96b8f7e2fc1..d0d66c28ee9c2 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/page_load_dist_chart.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/page_load_dist_chart.tsx @@ -5,148 +5,55 @@ * 2.0. */ -import React, { useState } from 'react'; -import numeral from '@elastic/numeral'; -import { - Axis, - BrushEndListener, - XYBrushEvent, - Chart, - CurveType, - LineSeries, - ScaleType, - Settings, - TooltipValue, - TooltipValueFormatter, - DARK_THEME, - LIGHT_THEME, - Fit, - Position, -} from '@elastic/charts'; -import { - EUI_CHARTS_THEME_DARK, - EUI_CHARTS_THEME_LIGHT, -} from '@elastic/eui/dist/eui_charts_theme'; -import styled from 'styled-components'; -import { useUiSetting$ } from '@kbn/kibana-react-plugin/public'; -import { PercentileAnnotations } from '../page_load_distribution/percentile_annotations'; -import { I18LABELS } from '../translations'; -import { ChartWrapper } from '../chart_wrapper'; -import { BreakdownSeries } from '../page_load_distribution/breakdown_series'; +import React from 'react'; +import { AllSeries } from '@kbn/observability-plugin/public'; +import { useExpViewAttributes } from './use_exp_view_attrs'; import { BreakdownItem } from '../../../../../typings/ui_filters'; -import { PercentileRange } from '../page_load_distribution/types'; - -interface PageLoadData { - pageLoadDistribution: Array<{ x: number; y: number }>; - percentiles: Record | undefined; - minDuration: number; - maxDuration: number; -} +import { useDataView } from '../local_uifilters/use_data_view'; +import { useKibanaServices } from '../../../../hooks/use_kibana_services'; +import { TRANSACTION_DURATION } from '../../../../../common/elasticsearch_fieldnames'; interface Props { - onPercentileChange: (min: number, max: number) => void; - data?: PageLoadData | null; breakdown: BreakdownItem | null; - percentileRange: PercentileRange; - loading: boolean; + onPercentileChange: (min: number, max: number) => void; } -const PageLoadChart = styled(Chart)` - .echAnnotation { - pointer-events: initial; - } -`; +export function PageLoadDistChart({ onPercentileChange, breakdown }: Props) { + const { dataViewTitle } = useDataView(); + + const kibana = useKibanaServices(); + const { ExploratoryViewEmbeddable } = kibana.observability!; -export function PageLoadDistChart({ - onPercentileChange, - data, - breakdown, - loading, - percentileRange, -}: Props) { - const [breakdownLoading, setBreakdownLoading] = useState(false); - const onBrushEnd = ({ x }: XYBrushEvent) => { - if (!x) { + const onBrushEnd = ({ range }: { range: number[] }) => { + if (!range) { return; } - const [minX, maxX] = x; + const [minX, maxX] = range; onPercentileChange(minX, maxX); }; - const headerFormatter: TooltipValueFormatter = (tooltip: TooltipValue) => { - return ( -
    -

    - {tooltip.value} {I18LABELS.seconds} -

    -
    - ); - }; - - const tooltipProps = { - headerFormatter, - }; - - const [darkMode] = useUiSetting$('theme:darkMode'); + const { reportDefinitions, time } = useExpViewAttributes(); - const euiChartTheme = darkMode - ? EUI_CHARTS_THEME_DARK - : EUI_CHARTS_THEME_LIGHT; + const allSeries: AllSeries = [ + { + time, + reportDefinitions, + dataType: 'ux', + name: 'page-load-distribution', + selectedMetricField: TRANSACTION_DURATION, + breakdown: breakdown?.fieldName, + }, + ]; return ( - - {(!loading || data) && ( - - - - - d + ' %'} - /> - numeral(d).format('0.0') + ' %'} - /> - {breakdown && ( - { - setBreakdownLoading(bLoading); - }} - /> - )} - - )} - + ); } diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/page_views_chart.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/page_views_chart.tsx index 2d763013157fb..4f8d0d4d2a06c 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/page_views_chart.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/page_views_chart.tsx @@ -9,7 +9,6 @@ import moment from 'moment'; import React from 'react'; import { AllSeries, - ALL_VALUES_SELECTED, fromQuery, RECORDS_FIELD, toQuery, @@ -17,50 +16,32 @@ import { } from '@kbn/observability-plugin/public'; import { useHistory } from 'react-router-dom'; -import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; -import { BreakdownItem, UxUIFilters } from '../../../../../typings/ui_filters'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; +import { BreakdownItem } from '../../../../../typings/ui_filters'; import { useKibanaServices } from '../../../../hooks/use_kibana_services'; import { useDataView } from '../local_uifilters/use_data_view'; -import { - SERVICE_ENVIRONMENT, - SERVICE_NAME, -} from '../../../../../common/elasticsearch_fieldnames'; +import { useExpViewAttributes } from './use_exp_view_attrs'; interface Props { breakdown: BreakdownItem | null; - uiFilters: UxUIFilters; } -export function PageViewsChart({ breakdown, uiFilters }: Props) { +export function PageViewsChart({ breakdown }: Props) { const { dataViewTitle } = useDataView(); const history = useHistory(); - const { urlParams } = useLegacyUrlParams(); const kibana = useKibanaServices(); const { ExploratoryViewEmbeddable } = kibana.observability; - const { start, end } = urlParams; const theme = useTheme(); + const { reportDefinitions, time } = useExpViewAttributes(); + const allSeries: AllSeries = [ { + time, + reportDefinitions, dataType: 'ux', - time: { - from: start ?? '', - to: end ?? '', - }, name: 'ux-series-1', selectedMetricField: RECORDS_FIELD, - reportDefinitions: { - [SERVICE_ENVIRONMENT]: - !uiFilters?.environment || - uiFilters.environment === ENVIRONMENT_ALL.value - ? [ALL_VALUES_SELECTED] - : [uiFilters.environment], - [SERVICE_NAME]: urlParams.serviceName - ? [urlParams.serviceName] - : [ALL_VALUES_SELECTED], - }, breakdown: breakdown?.fieldName, color: theme.eui.euiColorVis1, }, @@ -93,6 +74,7 @@ export function PageViewsChart({ breakdown, uiFilters }: Props) { dataTypesIndexPatterns={{ ux: dataViewTitle }} isSingleMetric={true} axisTitlesVisibility={{ x: false, yRight: true, yLeft: true }} + legendIsVisible={Boolean(breakdown)} /> ); } diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/use_exp_view_attrs.ts b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/use_exp_view_attrs.ts new file mode 100644 index 0000000000000..fb8eb5a0564e1 --- /dev/null +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/use_exp_view_attrs.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ALL_VALUES_SELECTED } from '@kbn/observability-plugin/public'; +import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; +import { + SERVICE_ENVIRONMENT, + SERVICE_NAME, +} from '../../../../../common/elasticsearch_fieldnames'; +import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; + +export const useExpViewAttributes = () => { + const { urlParams, uxUiFilters } = useLegacyUrlParams(); + + const { start, end } = urlParams; + + const reportDefinitions = { + [SERVICE_ENVIRONMENT]: + !uxUiFilters?.environment || + uxUiFilters.environment === ENVIRONMENT_ALL.value + ? [ALL_VALUES_SELECTED] + : [uxUiFilters.environment], + [SERVICE_NAME]: uxUiFilters?.serviceName ?? [ALL_VALUES_SELECTED], + }; + + return { + reportDefinitions, + time: { + from: start ?? '', + to: end ?? '', + }, + }; +}; diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/breakdown_series.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/breakdown_series.tsx deleted file mode 100644 index 0bd86a52c6e49..0000000000000 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/breakdown_series.tsx +++ /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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CurveType, Fit, LineSeries, ScaleType } from '@elastic/charts'; -import React, { useEffect } from 'react'; -import numeral from '@elastic/numeral'; -import { - EUI_CHARTS_THEME_DARK, - EUI_CHARTS_THEME_LIGHT, -} from '@elastic/eui/dist/eui_charts_theme'; -import { useUiSetting$ } from '@kbn/kibana-react-plugin/public'; -import { PercentileRange } from './types'; -import { useBreakdowns } from './use_breakdowns'; - -interface Props { - field: string; - value: string; - percentileRange: PercentileRange; - onLoadingChange: (loading: boolean) => void; -} - -export function BreakdownSeries({ - field, - value, - percentileRange, - onLoadingChange, -}: Props) { - const [darkMode] = useUiSetting$('theme:darkMode'); - - const euiChartTheme = darkMode - ? EUI_CHARTS_THEME_DARK - : EUI_CHARTS_THEME_LIGHT; - - const { breakdowns, status } = useBreakdowns({ - field, - value, - percentileRange, - }); - - useEffect(() => { - onLoadingChange(status !== 'success'); - }, [status, onLoadingChange]); - - // sort index 1 color vizColors1 is already used for overall, - // so don't user that here - return ( - <> - {breakdowns.map(({ data: seriesData, name }, sortIndex) => ( - numeral(d).format('0.0') + ' %'} - /> - ))} - - ); -} diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/index.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/index.tsx index 65487aaf66bf5..4ff4b47293cb3 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/index.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/index.tsx @@ -6,34 +6,15 @@ */ import React, { useState } from 'react'; -import { - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiTitle, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { createExploratoryViewUrl } from '@kbn/observability-plugin/public'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; -import { useFetcher } from '../../../../hooks/use_fetcher'; +import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import { I18LABELS } from '../translations'; import { BreakdownFilter } from '../breakdowns/breakdown_filter'; import { PageLoadDistChart } from '../charts/page_load_dist_chart'; import { ResetPercentileZoom } from './reset_percentile_zoom'; -import { useKibanaServices } from '../../../../hooks/use_kibana_services'; import { BreakdownItem } from '../../../../../typings/ui_filters'; import { PercentileRange } from './types'; export function PageLoadDistribution() { - const { http } = useKibanaServices(); - - const { rangeId, urlParams, uxUiFilters } = useLegacyUrlParams(); - - const { start, end, rangeFrom, rangeTo, searchTerm } = urlParams; - - const { serviceName } = uxUiFilters; - const [percentileRange, setPercentileRange] = useState({ min: null, max: null, @@ -41,66 +22,10 @@ export function PageLoadDistribution() { const [breakdown, setBreakdown] = useState(null); - const { data, status } = useFetcher( - (callApmApi) => { - if (start && end && serviceName) { - return callApmApi('GET /internal/apm/ux/page-load-distribution', { - params: { - query: { - start, - end, - uiFilters: JSON.stringify(uxUiFilters), - urlQuery: searchTerm, - ...(percentileRange.min && percentileRange.max - ? { - minPercentile: String(percentileRange.min), - maxPercentile: String(percentileRange.max), - } - : {}), - }, - }, - }); - } - return Promise.resolve(null); - }, - // `rangeId` acts as a cache buster for stable ranges like "Today" - // eslint-disable-next-line react-hooks/exhaustive-deps - [ - end, - start, - uxUiFilters, - percentileRange.min, - percentileRange.max, - searchTerm, - serviceName, - rangeId, - ] - ); - const onPercentileChange = (min: number, max: number) => { setPercentileRange({ min, max }); }; - const exploratoryViewLink = createExploratoryViewUrl( - { - reportType: 'kpi-over-time', - allSeries: [ - { - name: `${serviceName}-page-views`, - dataType: 'ux', - time: { from: rangeFrom!, to: rangeTo! }, - reportDefinitions: { - 'service.name': serviceName as string[], - }, - ...(breakdown ? { breakdown: breakdown.fieldName } : {}), - }, - ], - }, - http.basePath.get() - ); - - const showAnalyzeButton = false; - return (
    @@ -120,31 +45,10 @@ export function PageLoadDistribution() { dataTestSubj={'pldBreakdownFilter'} /> - {showAnalyzeButton && ( - - - - - - )} -
    ); diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/use_breakdowns.ts b/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/use_breakdowns.ts deleted file mode 100644 index ffe794ddceaee..0000000000000 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/page_load_distribution/use_breakdowns.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useFetcher } from '../../../../hooks/use_fetcher'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; -import { PercentileRange } from './types'; - -interface Props { - percentileRange?: PercentileRange; - field: string; - value: string; -} - -export const useBreakdowns = ({ percentileRange, field, value }: Props) => { - const { urlParams, uxUiFilters } = useLegacyUrlParams(); - const { start, end, searchTerm } = urlParams; - const { min: minP, max: maxP } = percentileRange ?? {}; - - const { data, status } = useFetcher( - (callApmApi) => { - if (start && end && field && value) { - return callApmApi( - 'GET /internal/apm/ux/page-load-distribution/breakdown', - { - params: { - query: { - start, - end, - breakdown: value, - uiFilters: JSON.stringify(uxUiFilters), - urlQuery: searchTerm, - ...(minP && maxP - ? { - minPercentile: String(minP), - maxPercentile: String(maxP), - } - : {}), - }, - }, - } - ); - } - }, - [end, start, uxUiFilters, field, value, minP, maxP, searchTerm] - ); - - return { breakdowns: data?.pageLoadDistBreakdown ?? [], status }; -}; diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/page_views_trend/index.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/page_views_trend/index.tsx index 733fbcf935c25..173865dc9ace0 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/page_views_trend/index.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/page_views_trend/index.tsx @@ -7,15 +7,12 @@ import React, { useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; -import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; import { I18LABELS } from '../translations'; import { BreakdownFilter } from '../breakdowns/breakdown_filter'; import { PageViewsChart } from '../charts/page_views_chart'; import { BreakdownItem } from '../../../../../typings/ui_filters'; export function PageViewsTrend() { - const { uxUiFilters } = useLegacyUrlParams(); - const [breakdown, setBreakdown] = useState(null); return ( @@ -34,7 +31,7 @@ export function PageViewsTrend() { />
    - +
    ); } diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/panels/page_load_and_views.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/panels/page_load_and_views.tsx index 0a4deee67786b..ef834227efbe8 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/panels/page_load_and_views.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/panels/page_load_and_views.tsx @@ -14,7 +14,7 @@ export function PageLoadAndViews() { return ( - + diff --git a/x-pack/test/accessibility/apps/tags.ts b/x-pack/test/accessibility/apps/tags.ts index 5369ad2d2db6b..7f56257b285c2 100644 --- a/x-pack/test/accessibility/apps/tags.ts +++ b/x-pack/test/accessibility/apps/tags.ts @@ -15,9 +15,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const retry = getService('retry'); const toasts = getService('toasts'); + const kibanaServer = getService('kibanaServer'); - describe('Kibana Tags Page Accessibility', () => { + // Failing: See https://github.com/elastic/kibana/issues/135339 + describe.skip('Kibana Tags Page Accessibility', () => { before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, }); @@ -33,6 +36,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.home.removeSampleDataSet('flights'); + await kibanaServer.savedObjects.cleanStandardList(); }); it('tags main page meets a11y validations', async () => { @@ -71,8 +75,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - // https://github.com/elastic/kibana/issues/135985 inconsistent test failure - it.skip('tag assignment panel meets a11y requirements', async () => { + it('tag assignment panel meets a11y requirements', async () => { await testSubjects.click('euiCollapsedItemActionsButton'); const actionOnTag = 'assign'; await PageObjects.tagManagement.clickActionItem(actionOnTag); @@ -80,14 +83,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('tag management page with connections column populated meets a11y requirements', async () => { - await testSubjects.click('euiCollapsedItemActionsButton'); - const actionOnTag = 'assign'; - await PageObjects.tagManagement.clickActionItem(actionOnTag); await testSubjects.click('assignFlyout-selectAllButton'); - await testSubjects.click('assignFlyoutConfirmButton'); await toasts.dismissAllToasts(); - await retry.try(async () => { await a11y.testAppSnapshot(); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts index 2d3829f42a678..e601c6ee15ec7 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts @@ -115,7 +115,6 @@ export default function createAlertTests({ getService }: FtrProviderContext) { created_by: user.username, schedule: { interval: '1m' }, scheduled_task_id: response.body.scheduled_task_id, - snooze_schedule: response.body.snooze_schedule, created_at: response.body.created_at, updated_at: response.body.updated_at, throttle: '1m', diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts index 177e51ab78eea..de51e6ad86118 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts @@ -73,7 +73,6 @@ const findTestUtils = ( params: {}, created_by: 'elastic', scheduled_task_id: match.scheduled_task_id, - snooze_schedule: match.snooze_schedule, created_at: match.created_at, updated_at: match.updated_at, throttle: '1m', @@ -83,7 +82,9 @@ const findTestUtils = ( mute_all: false, muted_alert_ids: [], execution_status: match.execution_status, - ...(describeType === 'internal' ? { monitoring: match.monitoring } : {}), + ...(describeType === 'internal' + ? { monitoring: match.monitoring, snooze_schedule: match.snooze_schedule } + : {}), }); expect(Date.parse(match.created_at)).to.be.greaterThan(0); expect(Date.parse(match.updated_at)).to.be.greaterThan(0); @@ -282,8 +283,9 @@ const findTestUtils = ( created_at: match.created_at, updated_at: match.updated_at, execution_status: match.execution_status, - snooze_schedule: match.snooze_schedule, - ...(describeType === 'internal' ? { monitoring: match.monitoring } : {}), + ...(describeType === 'internal' + ? { monitoring: match.monitoring, snooze_schedule: match.snooze_schedule } + : {}), }); expect(Date.parse(match.created_at)).to.be.greaterThan(0); expect(Date.parse(match.updated_at)).to.be.greaterThan(0); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts index c2c94af19b209..2752707843c0d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts @@ -72,7 +72,6 @@ const getTestUtils = ( params: {}, created_by: 'elastic', scheduled_task_id: response.body.scheduled_task_id, - snooze_schedule: response.body.snooze_schedule, updated_at: response.body.updated_at, created_at: response.body.created_at, throttle: '1m', @@ -85,6 +84,7 @@ const getTestUtils = ( ...(describeType === 'internal' ? { monitoring: response.body.monitoring, + snooze_schedule: response.body.snooze_schedule, } : {}), }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts index f0ce5962de368..ca3570a511d17 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts @@ -99,7 +99,6 @@ export default function createMuteAlertTests({ getService }: FtrProviderContext) .auth(user.username, user.password) .expect(200); expect(updatedAlert.mute_all).to.eql(true); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -156,7 +155,6 @@ export default function createMuteAlertTests({ getService }: FtrProviderContext) .auth(user.username, user.password) .expect(200); expect(updatedAlert.mute_all).to.eql(true); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -224,7 +222,6 @@ export default function createMuteAlertTests({ getService }: FtrProviderContext) .auth(user.username, user.password) .expect(200); expect(updatedAlert.mute_all).to.eql(true); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -292,7 +289,6 @@ export default function createMuteAlertTests({ getService }: FtrProviderContext) .auth(user.username, user.password) .expect(200); expect(updatedAlert.mute_all).to.eql(true); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts index 9c918b3225f9e..b4576650c58c8 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts @@ -104,7 +104,6 @@ export default function createUnmuteAlertTests({ getService }: FtrProviderContex .auth(user.username, user.password) .expect(200); expect(updatedAlert.mute_all).to.eql(false); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -166,7 +165,6 @@ export default function createUnmuteAlertTests({ getService }: FtrProviderContex .auth(user.username, user.password) .expect(200); expect(updatedAlert.mute_all).to.eql(false); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -239,7 +237,6 @@ export default function createUnmuteAlertTests({ getService }: FtrProviderContex .auth(user.username, user.password) .expect(200); expect(updatedAlert.mute_all).to.eql(false); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -312,7 +309,6 @@ export default function createUnmuteAlertTests({ getService }: FtrProviderContex .auth(user.username, user.password) .expect(200); expect(updatedAlert.mute_all).to.eql(false); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts index d28b81f479b11..c49fa62c606b6 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts @@ -129,7 +129,6 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { }, ], scheduled_task_id: createdAlert.scheduled_task_id, - snooze_schedule: createdAlert.snooze_schedule, created_at: response.body.created_at, updated_at: response.body.updated_at, execution_status: response.body.execution_status, @@ -214,7 +213,6 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { mute_all: false, muted_alert_ids: [], scheduled_task_id: createdAlert.scheduled_task_id, - snooze_schedule: createdAlert.snooze_schedule, created_at: response.body.created_at, updated_at: response.body.updated_at, execution_status: response.body.execution_status, @@ -310,7 +308,6 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { mute_all: false, muted_alert_ids: [], scheduled_task_id: createdAlert.scheduled_task_id, - snooze_schedule: createdAlert.snooze_schedule, created_at: response.body.created_at, updated_at: response.body.updated_at, execution_status: response.body.execution_status, @@ -406,7 +403,6 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { mute_all: false, muted_alert_ids: [], scheduled_task_id: createdAlert.scheduled_task_id, - snooze_schedule: createdAlert.snooze_schedule, created_at: response.body.created_at, updated_at: response.body.updated_at, execution_status: response.body.execution_status, @@ -500,7 +496,6 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { mute_all: false, muted_alert_ids: [], scheduled_task_id: createdAlert.scheduled_task_id, - snooze_schedule: createdAlert.snooze_schedule, created_at: response.body.created_at, updated_at: response.body.updated_at, execution_status: response.body.execution_status, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts index 5424b18599f64..c8161c54569b5 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts @@ -9,7 +9,10 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; +const ES_TEST_INDEX_NAME = 'functional-test-connectors-index'; +const ES_TEST_DATASTREAM_PREFIX = 'functional-test-connectors-ds'; +const ES_TEST_DATASTREAM_PATTERN_NAME = `${ES_TEST_DATASTREAM_PREFIX}-*`; +const ES_TEST_DATASTREAM_INDEX_NAME = `${ES_TEST_DATASTREAM_PREFIX}-00001`; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { @@ -17,62 +20,76 @@ export default function indexTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); - describe('index action', () => { - beforeEach(() => esDeleteAllIndices(ES_TEST_INDEX_NAME)); + describe('index connector', () => { + beforeEach(() => { + esDeleteAllIndices(ES_TEST_INDEX_NAME); + esDeleteAllIndices(ES_TEST_DATASTREAM_INDEX_NAME); + }); - let createdActionID: string; - let createdActionIDWithIndex: string; + after(async () => { + await es.transport.request({ + method: 'DELETE', + path: `/_data_stream/${ES_TEST_DATASTREAM_INDEX_NAME}`, + }); + await es.transport.request({ + method: 'DELETE', + path: `/_index_template/${ES_TEST_DATASTREAM_PREFIX}`, + }); + }); + + let createdConnectorID: string; + let createdConnectorIDWithIndex: string; it('should be created successfully', async () => { // create action with no config - const { body: createdAction } = await supertest - .post('/api/actions/action') + const { body: createdConnector } = await supertest + .post('/api/actions/connector') .set('kbn-xsrf', 'foo') .send({ - name: 'An index action', - actionTypeId: '.index', + name: 'An index connector', + connector_type_id: '.index', config: { index: ES_TEST_INDEX_NAME }, secrets: {}, }) .expect(200); - expect(createdAction).to.eql({ - id: createdAction.id, - isPreconfigured: false, - isDeprecated: false, - name: 'An index action', - actionTypeId: '.index', - isMissingSecrets: false, + expect(createdConnector).to.eql({ + id: createdConnector.id, + is_preconfigured: false, + is_deprecated: false, + name: 'An index connector', + connector_type_id: '.index', + is_missing_secrets: false, config: { index: ES_TEST_INDEX_NAME, refresh: false, executionTimeField: null, }, }); - createdActionID = createdAction.id; - expect(typeof createdActionID).to.be('string'); + createdConnectorID = createdConnector.id; + expect(typeof createdConnectorID).to.be('string'); - const { body: fetchedAction } = await supertest - .get(`/api/actions/action/${createdActionID}`) + const { body: fetchedConnector } = await supertest + .get(`/api/actions/connector/${createdConnectorID}`) .expect(200); - expect(fetchedAction).to.eql({ - id: fetchedAction.id, - isPreconfigured: false, - isDeprecated: false, - isMissingSecrets: false, - name: 'An index action', - actionTypeId: '.index', + expect(fetchedConnector).to.eql({ + id: fetchedConnector.id, + is_preconfigured: false, + is_deprecated: false, + is_missing_secrets: false, + name: 'An index connector', + connector_type_id: '.index', config: { index: ES_TEST_INDEX_NAME, refresh: false, executionTimeField: null }, }); - // create action with all config props - const { body: createdActionWithIndex } = await supertest - .post('/api/actions/action') + // create connector with all config props + const { body: createdConnectorWithIndex } = await supertest + .post('/api/actions/connector') .set('kbn-xsrf', 'foo') .send({ - name: 'An index action with index config', - actionTypeId: '.index', + name: 'An index connector with index config', + connector_type_id: '.index', config: { index: ES_TEST_INDEX_NAME, refresh: true, @@ -81,33 +98,33 @@ export default function indexTest({ getService }: FtrProviderContext) { }) .expect(200); - expect(createdActionWithIndex).to.eql({ - id: createdActionWithIndex.id, - isPreconfigured: false, - isDeprecated: false, - name: 'An index action with index config', - actionTypeId: '.index', - isMissingSecrets: false, + expect(createdConnectorWithIndex).to.eql({ + id: createdConnectorWithIndex.id, + is_preconfigured: false, + is_deprecated: false, + name: 'An index connector with index config', + connector_type_id: '.index', + is_missing_secrets: false, config: { index: ES_TEST_INDEX_NAME, refresh: true, executionTimeField: 'test', }, }); - createdActionIDWithIndex = createdActionWithIndex.id; - expect(typeof createdActionIDWithIndex).to.be('string'); + createdConnectorIDWithIndex = createdConnectorWithIndex.id; + expect(typeof createdConnectorIDWithIndex).to.be('string'); - const { body: fetchedActionWithIndex } = await supertest - .get(`/api/actions/action/${createdActionIDWithIndex}`) + const { body: fetchedConnectorWithIndex } = await supertest + .get(`/api/actions/connector/${createdConnectorIDWithIndex}`) .expect(200); - expect(fetchedActionWithIndex).to.eql({ - id: fetchedActionWithIndex.id, - isPreconfigured: false, - isDeprecated: false, - name: 'An index action with index config', - actionTypeId: '.index', - isMissingSecrets: false, + expect(fetchedConnectorWithIndex).to.eql({ + id: fetchedConnectorWithIndex.id, + is_preconfigured: false, + is_deprecated: false, + name: 'An index connector with index config', + connector_type_id: '.index', + is_missing_secrets: false, config: { index: ES_TEST_INDEX_NAME, refresh: true, @@ -116,13 +133,13 @@ export default function indexTest({ getService }: FtrProviderContext) { }); }); - it('should execute successly when expected for a single body', async () => { - const { body: createdAction } = await supertest - .post('/api/actions/action') + it('should execute successfully when expected for a single body', async () => { + const { body: createdConnector } = await supertest + .post('/api/actions/connector') .set('kbn-xsrf', 'foo') .send({ - name: 'An index action', - actionTypeId: '.index', + name: 'An index connector', + connector_type_id: '.index', config: { index: ES_TEST_INDEX_NAME, refresh: true, @@ -131,7 +148,7 @@ export default function indexTest({ getService }: FtrProviderContext) { }) .expect(200); const { body: result } = await supertest - .post(`/api/actions/action/${createdAction.id}/_execute`) + .post(`/api/actions/connector/${createdConnector.id}/_execute`) .set('kbn-xsrf', 'foo') .send({ params: { @@ -141,16 +158,68 @@ export default function indexTest({ getService }: FtrProviderContext) { .expect(200); expect(result.status).to.eql('ok'); - const items = await getTestIndexItems(es); + const items = await getTestIndexItems(es, ES_TEST_INDEX_NAME); expect(items.length).to.eql(1); expect(items[0]._source).to.eql({ testing: [1, 2, 3] }); }); + + it('should execute successfully into data stream', async () => { + await es.transport.request( + { + method: 'PUT', + path: `/_index_template/${ES_TEST_DATASTREAM_PREFIX}`, + body: { + index_patterns: [ES_TEST_DATASTREAM_PATTERN_NAME], + template: { + mappings: { + properties: { + '@timestamp': { + type: 'date', + }, + }, + }, + }, + data_stream: {}, + }, + }, + { meta: true } + ); + const { body: createdConnector } = await supertest + .post('/api/actions/connector') + .set('kbn-xsrf', 'foo') + .send({ + name: 'An index connector', + connector_type_id: '.index', + config: { + index: ES_TEST_DATASTREAM_INDEX_NAME, + refresh: true, + }, + secrets: {}, + }) + .expect(200); + + const timestamp = new Date().toISOString(); + const { body: result } = await supertest + .post(`/api/actions/connector/${createdConnector.id}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + documents: [{ '@timestamp': timestamp, testing_ds: [1, 2, 3] }], + }, + }) + .expect(200); + expect(result.status).to.eql('ok'); + + const items = await getTestIndexItems(es, ES_TEST_DATASTREAM_INDEX_NAME); + expect(items.length).to.eql(1); + expect(items[0]._source).to.eql({ '@timestamp': timestamp, testing_ds: [1, 2, 3] }); + }); }); } -async function getTestIndexItems(es: Client) { +async function getTestIndexItems(es: Client, indexName: string) { const result = await es.search({ - index: ES_TEST_INDEX_NAME, + index: indexName, }); return result.hits.hits; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts index a33f7fc5a1a2c..143d845d074c4 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts @@ -85,7 +85,6 @@ export default function createAlertTests({ getService }: FtrProviderContext) { created_by: null, schedule: { interval: '1m' }, scheduled_task_id: response.body.scheduled_task_id, - snooze_schedule: response.body.snooze_schedule, updated_by: null, api_key_owner: null, throttle: '1m', @@ -181,7 +180,6 @@ export default function createAlertTests({ getService }: FtrProviderContext) { created_by: null, schedule: { interval: '1m' }, scheduled_task_id: response.body.scheduled_task_id, - snooze_schedule: response.body.snooze_schedule, updated_by: null, api_key_owner: null, throttle: '1m', @@ -477,7 +475,6 @@ export default function createAlertTests({ getService }: FtrProviderContext) { createdBy: null, schedule: { interval: '1m' }, scheduledTaskId: response.body.scheduledTaskId, - snoozeSchedule: response.body.snoozeSchedule, updatedBy: null, apiKeyOwner: null, throttle: '1m', diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/find.ts index 021a2be1ebb5d..3162540538ff2 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/find.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/find.ts @@ -64,7 +64,6 @@ const findTestUtils = ( created_by: null, api_key_owner: null, scheduled_task_id: match.scheduled_task_id, - snooze_schedule: match.snooze_schedule, updated_by: null, throttle: '1m', notify_when: 'onThrottleInterval', @@ -73,7 +72,9 @@ const findTestUtils = ( created_at: match.created_at, updated_at: match.updated_at, execution_status: match.execution_status, - ...(describeType === 'internal' ? { monitoring: match.monitoring } : {}), + ...(describeType === 'internal' + ? { monitoring: match.monitoring, snooze_schedule: match.snooze_schedule } + : {}), }); expect(Date.parse(match.created_at)).to.be.greaterThan(0); expect(Date.parse(match.updated_at)).to.be.greaterThan(0); @@ -295,7 +296,6 @@ export default function createFindTests({ getService }: FtrProviderContext) { createdBy: null, apiKeyOwner: null, scheduledTaskId: match.scheduledTaskId, - snoozeSchedule: match.snoozeSchedule, updatedBy: null, throttle: '1m', notifyWhen: 'onThrottleInterval', diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get.ts index ee993c425fa38..d97eb3e2054b4 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get.ts @@ -45,7 +45,6 @@ const getTestUtils = ( params: {}, created_by: null, scheduled_task_id: response.body.scheduled_task_id, - snooze_schedule: response.body.snooze_schedule, updated_by: null, api_key_owner: null, throttle: '1m', @@ -137,7 +136,6 @@ export default function createGetTests({ getService }: FtrProviderContext) { params: {}, createdBy: null, scheduledTaskId: response.body.scheduledTaskId, - snoozeSchedule: response.body.snoozeSchedule, updatedBy: null, apiKeyOwner: null, throttle: '1m', diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/mute_all.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/mute_all.ts index a56b95ed09219..3fe13f8debe25 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/mute_all.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/mute_all.ts @@ -41,7 +41,6 @@ export default function createMuteTests({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'foo') .expect(200); expect(updatedAlert.mute_all).to.eql(true); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ supertest: supertestWithoutAuth, @@ -70,7 +69,6 @@ export default function createMuteTests({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'foo') .expect(200); expect(updatedAlert.mute_all).to.eql(true); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/unmute_all.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/unmute_all.ts index 62ff63052f841..47f61250157a3 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/unmute_all.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/unmute_all.ts @@ -42,7 +42,6 @@ export default function createUnmuteTests({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'foo') .expect(200); expect(updatedAlert.mute_all).to.eql(false); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ @@ -76,7 +75,6 @@ export default function createUnmuteTests({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'foo') .expect(200); expect(updatedAlert.mute_all).to.eql(false); - expect(updatedAlert.snooze_schedule.length).to.eql(0); // Ensure AAD isn't broken await checkAAD({ diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/update.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/update.ts index c431654f0fd20..c5a9c93d45e81 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/update.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/update.ts @@ -60,7 +60,6 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { muted_alert_ids: [], notify_when: 'onThrottleInterval', scheduled_task_id: createdAlert.scheduled_task_id, - snooze_schedule: createdAlert.snooze_schedule, created_at: response.body.created_at, updated_at: response.body.updated_at, execution_status: response.body.execution_status, @@ -161,7 +160,6 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { mutedInstanceIds: [], notifyWhen: 'onThrottleInterval', scheduledTaskId: createdAlert.scheduled_task_id, - snoozeSchedule: createdAlert.snooze_schedule, createdAt: response.body.createdAt, updatedAt: response.body.updatedAt, executionStatus: response.body.executionStatus, diff --git a/x-pack/test/api_integration/apis/index.ts b/x-pack/test/api_integration/apis/index.ts index 6bec2ebe80a13..46b10af2a52b3 100644 --- a/x-pack/test/api_integration/apis/index.ts +++ b/x-pack/test/api_integration/apis/index.ts @@ -36,5 +36,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./watcher')); loadTestFile(require.resolve('./logs_ui')); loadTestFile(require.resolve('./osquery')); + loadTestFile(require.resolve('./monitoring_collection')); }); } diff --git a/x-pack/test/api_integration/apis/monitoring_collection/index.ts b/x-pack/test/api_integration/apis/monitoring_collection/index.ts new file mode 100644 index 0000000000000..e89bd44963c03 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring_collection/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Monitoring Collection', function taskManagerSuite() { + loadTestFile(require.resolve('./prometheus')); + }); +} diff --git a/x-pack/test/api_integration/apis/monitoring_collection/prometheus.ts b/x-pack/test/api_integration/apis/monitoring_collection/prometheus.ts new file mode 100644 index 0000000000000..0ac13dda92cb5 --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring_collection/prometheus.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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('Prometheus endpoint', () => { + it('returns prometheus scraped metrics', async () => { + await supertest.post('/api/generate_otel_metrics').set('kbn-xsrf', 'foo').expect(200); + const response = await supertest.get('/api/monitoring_collection/v1/prometheus').expect(200); + + expect(response.text.replace(/\s+/g, ' ')).to.match( + /^# HELP request_count_total Counts total number of requests # TYPE request_count_total counter request_count_total [0-9]/ + ); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/uptime/rest/index_status.ts b/x-pack/test/api_integration/apis/uptime/rest/index_status.ts index 620621274a078..6526278bb8a46 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/index_status.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/index_status.ts @@ -10,7 +10,8 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; import { expectFixtureEql } from './helper/expect_fixture_eql'; export default function ({ getService }: FtrProviderContext) { - describe('docCount query', () => { + // Failing ES Promotion: https://github.com/elastic/kibana/issues/136412 + describe.skip('docCount query', () => { const supertest = getService('supertest'); it(`will fetch the index's count`, async () => { diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts index 8cc5fb6f57d42..ca3795e812ee2 100644 --- a/x-pack/test/api_integration/config.ts +++ b/x-pack/test/api_integration/config.ts @@ -37,6 +37,7 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi '--xpack.ruleRegistry.write.cache.enabled=false', '--xpack.uptime.service.password=test', '--xpack.uptime.service.username=localKibanaIntegrationTestsUser', + '--monitoring_collection.opentelemetry.metrics.prometheus.enabled=true', ], }, esTestCluster: { diff --git a/x-pack/test/apm_api_integration/tests/services/sorted_and_filtered_services.spec.ts b/x-pack/test/apm_api_integration/tests/services/sorted_and_filtered_services.spec.ts index b0e29debb62af..fe29e3e795684 100644 --- a/x-pack/test/apm_api_integration/tests/services/sorted_and_filtered_services.spec.ts +++ b/x-pack/test/apm_api_integration/tests/services/sorted_and_filtered_services.spec.ts @@ -50,7 +50,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { type ServiceListItem = ValuesType>>; - registry.when( + // FLAKY: https://github.com/elastic/kibana/issues/127939 + registry.when.skip( 'Sorted and filtered services', { config: 'trial', archives: ['apm_mappings_only_8.0.0'] }, () => { diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/runtime.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/runtime.ts index e6d1ef69f0913..6c6b33d4a54e3 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/runtime.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/runtime.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { performance } from 'perf_hooks'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { @@ -49,6 +50,15 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllAlerts(supertest, log); }); + it('should execute a rule to completion and not timeout when there are a lot of runtime fields', async () => { + const rule = getRuleForSignalTesting(['runtime']); + const { id } = await createRule(supertest, log, rule); + const start = performance.now(); + await waitForRuleSuccessOrStatus(supertest, log, id); + const end = performance.now(); + expect(end - start).to.be.lessThan(10000); + }); + it('should copy normal non-runtime data set from the source index into the signals index in the same position when the target is ECS compatible', async () => { const rule = getRuleForSignalTesting(['runtime']); const { id } = await createRule(supertest, log, rule); diff --git a/x-pack/test/examples/config.ts b/x-pack/test/examples/config.ts index 16db620e76598..fe01c4ecf0e44 100644 --- a/x-pack/test/examples/config.ts +++ b/x-pack/test/examples/config.ts @@ -8,8 +8,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; import { resolve } from 'path'; import fs from 'fs'; -// @ts-expect-error https://github.com/elastic/kibana/issues/95679 -import { KIBANA_ROOT } from '@kbn/test'; +import { REPO_ROOT as KIBANA_ROOT } from '@kbn/utils'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xpackFunctionalConfig = await readConfigFile( diff --git a/x-pack/test/fleet_api_integration/apis/download_sources/crud.ts b/x-pack/test/fleet_api_integration/apis/download_sources/crud.ts index af9a109ed62ce..e8afeec2632c5 100644 --- a/x-pack/test/fleet_api_integration/apis/download_sources/crud.ts +++ b/x-pack/test/fleet_api_integration/apis/download_sources/crud.ts @@ -50,9 +50,9 @@ export default function (providerContext: FtrProviderContext) { expect(downloadSource.items[0]).to.eql({ id: 'fleet-default-download-source', - name: 'default', + name: 'Elastic Artifacts', is_default: true, - host: 'https://artifacts.elastic.co', + host: 'https://artifacts.elastic.co/downloads/beats/elastic-agent', }); }); }); @@ -66,9 +66,9 @@ export default function (providerContext: FtrProviderContext) { expect(downloadSource).to.eql({ item: { id: 'fleet-default-download-source', - name: 'default', + name: 'Elastic Artifacts', is_default: true, - host: 'https://artifacts.elastic.co', + host: 'https://artifacts.elastic.co/downloads/beats/elastic-agent', }, }); }); diff --git a/x-pack/test/functional/apps/discover/async_scripted_fields.js b/x-pack/test/functional/apps/discover/async_scripted_fields.js index 2c18051405964..ba670ad78aa32 100644 --- a/x-pack/test/functional/apps/discover/async_scripted_fields.js +++ b/x-pack/test/functional/apps/discover/async_scripted_fields.js @@ -23,8 +23,8 @@ export default function ({ getService, getPageObjects }) { this.tags(['skipFirefox']); before(async function () { - await esArchiver.load( - 'x-pack/test/functional/es_archives/kibana_scripted_fields_on_logstash' + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/kibana_scripted_fields_on_logstash' ); await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await security.testUser.setRoles(['test_logstash_reader', 'global_discover_read']); @@ -39,7 +39,7 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.uiSettings.replace({}); await kibanaServer.uiSettings.update({}); await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional'); - await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); + await kibanaServer.savedObjects.cleanStandardList(); await security.testUser.restoreDefaults(); }); diff --git a/x-pack/test/functional/apps/infra/tour.ts b/x-pack/test/functional/apps/infra/tour.ts index 9806115c6129f..8a3cda46efcd8 100644 --- a/x-pack/test/functional/apps/infra/tour.ts +++ b/x-pack/test/functional/apps/infra/tour.ts @@ -6,6 +6,10 @@ */ import expect from '@kbn/expect'; +import { + observTourActiveStorageKey, + observTourStepStorageKey, +} from '@kbn/observability-plugin/public/components/shared/tour'; import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ getPageObjects, getService }: FtrProviderContext) => { @@ -15,13 +19,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const find = getService('find'); const setInitialTourState = async (activeStep?: number) => { - await browser.setLocalStorageItem( - 'xpack.observability.tourState', - JSON.stringify({ - activeStep: activeStep || 1, - isTourActive: true, - }) - ); + await browser.setLocalStorageItem(observTourActiveStorageKey, 'true'); + await browser.setLocalStorageItem(observTourStepStorageKey, String(activeStep || 1)); await browser.refresh(); }; @@ -31,11 +30,14 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); await pageObjects.common.navigateToApp('observability'); + // Need to increase the browser height so the tour steps fit to screen + await browser.setWindowSize(1600, 1400); }); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); - await browser.removeLocalStorageItem('xpack.observability.tourState'); + await browser.removeLocalStorageItem(observTourActiveStorageKey); + await browser.removeLocalStorageItem(observTourStepStorageKey); }); describe('Tour enabled', () => { @@ -45,22 +47,27 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // Step 1: Overview await pageObjects.infraHome.waitForTourStep('overviewStep'); await pageObjects.infraHome.clickTourNextButton(); + await pageObjects.infraHome.ensureTourStepIsClosed('overviewStep'); // Step 2: Streams await pageObjects.infraHome.waitForTourStep('streamStep'); await pageObjects.infraHome.clickTourNextButton(); + await pageObjects.infraHome.ensureTourStepIsClosed('streamStep'); // Step 3: Metrics explorer await pageObjects.infraHome.waitForTourStep('metricsExplorerStep'); await pageObjects.infraHome.clickTourNextButton(); + await pageObjects.infraHome.ensureTourStepIsClosed('metricsExplorerStep'); // Step 4: Traces await pageObjects.infraHome.waitForTourStep('tracesStep'); await pageObjects.infraHome.clickTourNextButton(); + await pageObjects.infraHome.ensureTourStepIsClosed('tracesStep'); // Step 5: Alerts await pageObjects.infraHome.waitForTourStep('alertStep'); await pageObjects.infraHome.clickTourNextButton(); + await pageObjects.infraHome.ensureTourStepIsClosed('alertStep'); // Step 6: Guided setup await pageObjects.infraHome.waitForTourStep('guidedSetupStep'); @@ -92,6 +99,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // Step 5: Alerts await pageObjects.infraHome.waitForTourStep('alertStep'); await pageObjects.infraHome.clickTourNextButton(); + await pageObjects.infraHome.ensureTourStepIsClosed('alertStep'); // Step 6: Guided setup await pageObjects.infraHome.waitForTourStep('guidedSetupStep'); diff --git a/x-pack/test/functional/apps/lens/group3/lens_reporting.ts b/x-pack/test/functional/apps/lens/group3/lens_reporting.ts index 2cbb55ae03d97..dd54475efff32 100644 --- a/x-pack/test/functional/apps/lens/group3/lens_reporting.ts +++ b/x-pack/test/functional/apps/lens/group3/lens_reporting.ts @@ -11,13 +11,15 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'reporting', 'timePicker']); const es = getService('es'); - const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); const listingTable = getService('listingTable'); const security = getService('security'); describe('lens reporting', () => { before(async () => { - await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/lens/reporting'); + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/lens/reporting' + ); await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await security.testUser.setRoles( [ @@ -30,7 +32,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/lens/reporting'); + await kibanaServer.savedObjects.cleanStandardList(); await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings(); await es.deleteByQuery({ index: '.reporting-*', diff --git a/x-pack/test/functional/apps/maps/group1/sample_data.js b/x-pack/test/functional/apps/maps/group1/sample_data.js index a8ebc8ec6ba85..d9ef08ef712f1 100644 --- a/x-pack/test/functional/apps/maps/group1/sample_data.js +++ b/x-pack/test/functional/apps/maps/group1/sample_data.js @@ -68,7 +68,7 @@ export default function ({ getPageObjects, getService, updateBaselines }) { describe('ecommerce', () => { before(async () => { await PageObjects.maps.loadSavedMap('[eCommerce] Orders by Country'); - await PageObjects.maps.toggleLayerVisibility('Road map - desaturated'); + await PageObjects.maps.toggleEmsBasemapLayerVisibility(); await PageObjects.maps.toggleLayerVisibility('United Kingdom'); await PageObjects.maps.toggleLayerVisibility('France'); await PageObjects.maps.toggleLayerVisibility('United States'); @@ -96,7 +96,7 @@ export default function ({ getPageObjects, getService, updateBaselines }) { describe('flights', () => { before(async () => { await PageObjects.maps.loadSavedMap('[Flights] Origin Time Delayed'); - await PageObjects.maps.toggleLayerVisibility('Road map - desaturated'); + await PageObjects.maps.toggleEmsBasemapLayerVisibility(); await PageObjects.timePicker.setCommonlyUsedTime('sample_data range'); await PageObjects.maps.enterFullScreen(); await PageObjects.maps.closeLegend(); @@ -121,7 +121,7 @@ export default function ({ getPageObjects, getService, updateBaselines }) { before(async () => { await PageObjects.maps.loadSavedMap('[Logs] Total Requests and Bytes'); await PageObjects.maps.toggleLayerVisibility('Total Requests by Destination'); - await PageObjects.maps.toggleLayerVisibility('Road map - desaturated'); + await PageObjects.maps.toggleEmsBasemapLayerVisibility(); await PageObjects.timePicker.setCommonlyUsedTime('sample_data range'); await PageObjects.maps.enterFullScreen(); await PageObjects.maps.closeLegend(); diff --git a/x-pack/test/functional/apps/maps/group2/embeddable/filter_by_map_extent.js b/x-pack/test/functional/apps/maps/group2/embeddable/filter_by_map_extent.js index c244dc06d6e0f..9f28af2e9a25d 100644 --- a/x-pack/test/functional/apps/maps/group2/embeddable/filter_by_map_extent.js +++ b/x-pack/test/functional/apps/maps/group2/embeddable/filter_by_map_extent.js @@ -8,6 +8,7 @@ export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'lens', 'maps']); + const browser = getService('browser'); const testSubjects = getService('testSubjects'); const dashboardPanelActions = getService('dashboardPanelActions'); const security = getService('security'); @@ -35,7 +36,12 @@ export default function ({ getPageObjects, getService }) { it('should filter dashboard by map extent when "filter by map extent" is enabled', async () => { const mapPanelHeader = await dashboardPanelActions.getPanelHeading('document example'); await dashboardPanelActions.openContextMenuMorePanel(mapPanelHeader); - await await testSubjects.click('embeddablePanelAction-FILTER_BY_MAP_EXTENT'); + await testSubjects.click('embeddablePanelAction-FILTER_BY_MAP_EXTENT'); + await testSubjects.setEuiSwitch( + 'filterByMapExtentSwitch24ade730-afe4-42b6-919a-c4e0a98c94f2', + 'check' + ); + await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.lens.assertMetric('Count of records', '1'); @@ -50,7 +56,12 @@ export default function ({ getPageObjects, getService }) { it('should remove map extent filter dashboard when "filter by map extent" is disabled', async () => { const mapPanelHeader = await dashboardPanelActions.getPanelHeading('document example'); await dashboardPanelActions.openContextMenuMorePanel(mapPanelHeader); - await await testSubjects.click('embeddablePanelAction-FILTER_BY_MAP_EXTENT'); + await testSubjects.click('embeddablePanelAction-FILTER_BY_MAP_EXTENT'); + await testSubjects.setEuiSwitch( + 'filterByMapExtentSwitch24ade730-afe4-42b6-919a-c4e0a98c94f2', + 'uncheck' + ); + await browser.pressKeys(browser.keys.ESCAPE); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.lens.assertMetric('Count of records', '6'); }); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts index a86be2bbaaa8d..3a33c95edba42 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts @@ -135,8 +135,7 @@ export default function ({ getService }: FtrProviderContext) { }); for (const testData of testDataList) { - // FLAKY: https://github.com/elastic/kibana/issues/134430 - describe.skip(`${testData.suiteTitle}`, function () { + describe(`${testData.suiteTitle}`, function () { const cloneJobId = `${testData.job.id}_clone`; const cloneDestIndex = `${testData.job!.dest!.index}_clone`; diff --git a/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts b/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts index 0d08a04b3ea26..b7e292e945a4f 100644 --- a/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts +++ b/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts @@ -226,7 +226,9 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('should display enabled AD job row action buttons'); await ml.jobTable.assertJobActionsMenuButtonEnabled(adJobId, true); await ml.jobTable.assertJobActionStartDatafeedButtonEnabled(adJobId, true); + await ml.jobTable.assertJobActionResetJobButtonEnabled(adJobId, true); await ml.jobTable.assertJobActionCloneJobButtonEnabled(adJobId, true); + await ml.jobTable.assertJobActionViewDatafeedCountsButtonEnabled(adJobId, true); await ml.jobTable.assertJobActionEditJobButtonEnabled(adJobId, true); await ml.jobTable.assertJobActionDeleteJobButtonEnabled(adJobId, true); diff --git a/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts b/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts index e9ec6d7bfc1d6..bc4c81ccf7f2d 100644 --- a/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts +++ b/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts @@ -208,8 +208,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await ml.jobTable.assertJobActionSingleMetricViewerButtonEnabled(adJobId, true); await ml.jobTable.assertJobActionAnomalyExplorerButtonEnabled(adJobId, true); - await ml.testExecution.logTestStep('should display disabled AD job row action button'); - await ml.jobTable.assertJobActionsMenuButtonEnabled(adJobId, false); + await ml.testExecution.logTestStep( + 'should display enabled AD job row view datafeed counts action' + ); + await ml.jobTable.assertJobActionsMenuButtonEnabled(adJobId, true); + await ml.jobTable.assertJobActionViewDatafeedCountsButtonEnabled(adJobId, true); + + await ml.testExecution.logTestStep( + 'should display expected disabled AD job row actions' + ); + await ml.jobTable.assertJobActionStartDatafeedButtonEnabled(adJobId, false); + await ml.jobTable.assertJobActionResetJobButtonEnabled(adJobId, false); + await ml.jobTable.assertJobActionCloneJobButtonEnabled(adJobId, false); + await ml.jobTable.assertJobActionEditJobButtonEnabled(adJobId, false); + await ml.jobTable.assertJobActionDeleteJobButtonEnabled(adJobId, false); await ml.testExecution.logTestStep('should select the job'); await ml.jobTable.selectJobRow(adJobId); diff --git a/x-pack/test/functional/es_archives/kibana_scripted_fields_on_logstash/data.json.gz b/x-pack/test/functional/es_archives/kibana_scripted_fields_on_logstash/data.json.gz deleted file mode 100644 index 1e57c64f2d7df..0000000000000 Binary files a/x-pack/test/functional/es_archives/kibana_scripted_fields_on_logstash/data.json.gz and /dev/null differ diff --git a/x-pack/test/functional/es_archives/kibana_scripted_fields_on_logstash/mappings.json b/x-pack/test/functional/es_archives/kibana_scripted_fields_on_logstash/mappings.json deleted file mode 100644 index e0dd6d90eacb4..0000000000000 --- a/x-pack/test/functional/es_archives/kibana_scripted_fields_on_logstash/mappings.json +++ /dev/null @@ -1,2717 +0,0 @@ -{ - "type": "index", - "value": { - "aliases": { - ".kibana": { - } - }, - "index": ".kibana_1", - "mappings": { - "_meta": { - "migrationMappingPropertyHashes": { - "action": "6e96ac5e648f57523879661ea72525b7", - "action_task_params": "a9d49f184ee89641044be0ca2950fa3a", - "alert": "7b44fba6773e37c806ce290ea9b7024e", - "apm-indices": "9bb9b2bf1fa636ed8619cbab5ce6a1dd", - "apm-telemetry": "3525d7c22c42bc80f5e6e9cb3f2b26a2", - "application_usage_totals": "c897e4310c5f24b07caaff3db53ae2c1", - "application_usage_transactional": "965839e75f809fefe04f92dc4d99722a", - "canvas-element": "7390014e1091044523666d97247392fc", - "canvas-workpad": "b0a1706d356228dbdcb4a17e6b9eb231", - "cases": "08b8b110dbca273d37e8aef131ecab61", - "cases-comments": "c2061fb929f585df57425102fa928b4b", - "cases-configure": "42711cbb311976c0687853f4c1354572", - "cases-user-actions": "32277330ec6b721abe3b846cfd939a71", - "config": "ae24d22d5986d04124cc6568f771066f", - "dashboard": "d00f614b29a80360e1190193fd333bab", - "file-upload-telemetry": "0ed4d3e1983d1217a30982630897092e", - "graph-workspace": "cd7ba1330e6682e9cc00b78850874be1", - "index-pattern": "66eccb05066c5a89924f48a9e9736499", - "infrastructure-ui-source": "ddc0ecb18383f6b26101a2fadb2dab0c", - "inventory-view": "5299b67717e96502c77babf1c16fd4d3", - "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", - "lens": "21c3ea0763beb1ecb0162529706b88c5", - "lens-ui-telemetry": "509bfa5978586998e05f9e303c07a327", - "maps-telemetry": "268da3a48066123fc5baf35abaa55014", - "metrics-explorer-view": "53c5365793677328df0ccb6138bf3cdd", - "migrationVersion": "4a1746014a75ade3a714e1db5763276f", - "ml-telemetry": "257fd1d4b4fdbb9cb4b8a3b27da201e9", - "namespace": "2f4316de49999235636386fe51dc06c1", - "namespaces": "2f4316de49999235636386fe51dc06c1", - "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9", - "references": "7997cf5a56cc02bdc9c93361bde732b0", - "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", - "search": "181661168bbadd1eff5902361e2a0d5c", - "server": "ec97f1c5da1a19609a60874e5af1100c", - "siem-detection-engine-rule-actions": "6569b288c169539db10cb262bf79de18", - "siem-detection-engine-rule-status": "ae783f41c6937db6b7a2ef5c93a9e9b0", - "siem-ui-timeline": "f2d929253ecd06ffbac78b4047f45a86", - "siem-ui-timeline-note": "8874706eedc49059d4cf0f5094559084", - "siem-ui-timeline-pinned-event": "20638091112f0e14f0e443d512301c29", - "space": "c5ca8acafa0beaa4d08d014a97b6bc6b", - "telemetry": "36a616f7026dfa617d6655df850fe16d", - "tsvb-validation-telemetry": "3a37ef6c8700ae6fc97d5c7da00e9215", - "type": "2f4316de49999235636386fe51dc06c1", - "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3", - "updated_at": "00da57df13e94e9d98437d13ace4bfe0", - "upgrade-assistant-reindex-operation": "296a89039fc4260292be36b1b005d8f2", - "upgrade-assistant-telemetry": "56702cec857e0a9dacfb696655b4ff7b", - "uptime-dynamic-settings": "a6f3af21b612339cbe6eecc1e5a60871", - "url": "b675c3be8d76ecf029294d51dc7ec65d", - "visualization": "52d7a13ad68a150c4525b292d23e12cc" - } - }, - "dynamic": "strict", - "properties": { - "action": { - "properties": { - "actionTypeId": { - "type": "keyword" - }, - "config": { - "enabled": false, - "type": "object" - }, - "name": { - "fields": { - "keyword": { - "type": "keyword" - } - }, - "type": "text" - }, - "secrets": { - "type": "binary" - } - } - }, - "action_task_params": { - "properties": { - "actionId": { - "type": "keyword" - }, - "apiKey": { - "type": "binary" - }, - "params": { - "enabled": false, - "type": "object" - } - } - }, - "alert": { - "properties": { - "actions": { - "properties": { - "actionRef": { - "type": "keyword" - }, - "actionTypeId": { - "type": "keyword" - }, - "group": { - "type": "keyword" - }, - "params": { - "enabled": false, - "type": "object" - } - }, - "type": "nested" - }, - "alertTypeId": { - "type": "keyword" - }, - "apiKey": { - "type": "binary" - }, - "apiKeyOwner": { - "type": "keyword" - }, - "consumer": { - "type": "keyword" - }, - "createdAt": { - "type": "date" - }, - "createdBy": { - "type": "keyword" - }, - "enabled": { - "type": "boolean" - }, - "muteAll": { - "type": "boolean" - }, - "mutedInstanceIds": { - "type": "keyword" - }, - "name": { - "fields": { - "keyword": { - "type": "keyword" - } - }, - "type": "text" - }, - "params": { - "enabled": false, - "type": "object" - }, - "schedule": { - "properties": { - "interval": { - "type": "keyword" - } - } - }, - "scheduledTaskId": { - "type": "keyword" - }, - "tags": { - "type": "keyword" - }, - "throttle": { - "type": "keyword" - }, - "updatedBy": { - "type": "keyword" - } - } - }, - "apm-indices": { - "properties": { - "error": { - "type": "keyword" - }, - "metric": { - "type": "keyword" - }, - "onboarding": { - "type": "keyword" - }, - "sourcemap": { - "type": "keyword" - }, - "span": { - "type": "keyword" - }, - "transaction": { - "type": "keyword" - } - } - }, - "apm-telemetry": { - "properties": { - "agents": { - "properties": { - "dotnet": { - "properties": { - "agent": { - "properties": { - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "service": { - "properties": { - "framework": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "language": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "runtime": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - }, - "go": { - "properties": { - "agent": { - "properties": { - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "service": { - "properties": { - "framework": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "language": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "runtime": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - }, - "java": { - "properties": { - "agent": { - "properties": { - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "service": { - "properties": { - "framework": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "language": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "runtime": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - }, - "js-base": { - "properties": { - "agent": { - "properties": { - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "service": { - "properties": { - "framework": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "language": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "runtime": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - }, - "nodejs": { - "properties": { - "agent": { - "properties": { - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "service": { - "properties": { - "framework": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "language": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "runtime": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - }, - "python": { - "properties": { - "agent": { - "properties": { - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "service": { - "properties": { - "framework": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "language": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "runtime": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - }, - "ruby": { - "properties": { - "agent": { - "properties": { - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "service": { - "properties": { - "framework": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "language": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "runtime": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - }, - "rum-js": { - "properties": { - "agent": { - "properties": { - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "service": { - "properties": { - "framework": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "language": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "runtime": { - "properties": { - "composite": { - "ignore_above": 1024, - "type": "keyword" - }, - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "version": { - "ignore_above": 1024, - "type": "keyword" - } - } - } - } - } - } - } - } - }, - "cardinality": { - "properties": { - "transaction": { - "properties": { - "name": { - "properties": { - "all_agents": { - "properties": { - "1d": { - "type": "long" - } - } - }, - "rum": { - "properties": { - "1d": { - "type": "long" - } - } - } - } - } - } - }, - "user_agent": { - "properties": { - "original": { - "properties": { - "all_agents": { - "properties": { - "1d": { - "type": "long" - } - } - }, - "rum": { - "properties": { - "1d": { - "type": "long" - } - } - } - } - } - } - } - } - }, - "counts": { - "properties": { - "agent_configuration": { - "properties": { - "all": { - "type": "long" - } - } - }, - "error": { - "properties": { - "1d": { - "type": "long" - }, - "all": { - "type": "long" - } - } - }, - "max_error_groups_per_service": { - "properties": { - "1d": { - "type": "long" - } - } - }, - "max_transaction_groups_per_service": { - "properties": { - "1d": { - "type": "long" - } - } - }, - "metric": { - "properties": { - "1d": { - "type": "long" - }, - "all": { - "type": "long" - } - } - }, - "onboarding": { - "properties": { - "1d": { - "type": "long" - }, - "all": { - "type": "long" - } - } - }, - "services": { - "properties": { - "1d": { - "type": "long" - } - } - }, - "sourcemap": { - "properties": { - "1d": { - "type": "long" - }, - "all": { - "type": "long" - } - } - }, - "span": { - "properties": { - "1d": { - "type": "long" - }, - "all": { - "type": "long" - } - } - }, - "traces": { - "properties": { - "1d": { - "type": "long" - } - } - }, - "transaction": { - "properties": { - "1d": { - "type": "long" - }, - "all": { - "type": "long" - } - } - } - } - }, - "has_any_services": { - "type": "boolean" - }, - "indices": { - "properties": { - "all": { - "properties": { - "total": { - "properties": { - "docs": { - "properties": { - "count": { - "type": "long" - } - } - }, - "store": { - "properties": { - "size_in_bytes": { - "type": "long" - } - } - } - } - } - } - }, - "shards": { - "properties": { - "total": { - "type": "long" - } - } - } - } - }, - "integrations": { - "properties": { - "ml": { - "properties": { - "all_jobs_count": { - "type": "long" - } - } - } - } - }, - "retainment": { - "properties": { - "error": { - "properties": { - "ms": { - "type": "long" - } - } - }, - "metric": { - "properties": { - "ms": { - "type": "long" - } - } - }, - "onboarding": { - "properties": { - "ms": { - "type": "long" - } - } - }, - "span": { - "properties": { - "ms": { - "type": "long" - } - } - }, - "transaction": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "services_per_agent": { - "properties": { - "dotnet": { - "null_value": 0, - "type": "long" - }, - "go": { - "null_value": 0, - "type": "long" - }, - "java": { - "null_value": 0, - "type": "long" - }, - "js-base": { - "null_value": 0, - "type": "long" - }, - "nodejs": { - "null_value": 0, - "type": "long" - }, - "python": { - "null_value": 0, - "type": "long" - }, - "ruby": { - "null_value": 0, - "type": "long" - }, - "rum-js": { - "null_value": 0, - "type": "long" - } - } - }, - "tasks": { - "properties": { - "agent_configuration": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "agents": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "cardinality": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "groupings": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "indices_stats": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "integrations": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "processor_events": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "services": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - }, - "versions": { - "properties": { - "took": { - "properties": { - "ms": { - "type": "long" - } - } - } - } - } - } - }, - "version": { - "properties": { - "apm_server": { - "properties": { - "major": { - "type": "long" - }, - "minor": { - "type": "long" - }, - "patch": { - "type": "long" - } - } - } - } - } - } - }, - "application_usage_totals": { - "properties": { - "appId": { - "type": "keyword" - }, - "minutesOnScreen": { - "type": "float" - }, - "numberOfClicks": { - "type": "long" - } - } - }, - "application_usage_transactional": { - "properties": { - "appId": { - "type": "keyword" - }, - "minutesOnScreen": { - "type": "float" - }, - "numberOfClicks": { - "type": "long" - }, - "timestamp": { - "type": "date" - } - } - }, - "canvas-element": { - "dynamic": "false", - "properties": { - "@created": { - "type": "date" - }, - "@timestamp": { - "type": "date" - }, - "content": { - "type": "text" - }, - "help": { - "type": "text" - }, - "image": { - "type": "text" - }, - "name": { - "fields": { - "keyword": { - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "canvas-workpad": { - "dynamic": "false", - "properties": { - "@created": { - "type": "date" - }, - "@timestamp": { - "type": "date" - }, - "name": { - "fields": { - "keyword": { - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "cases": { - "properties": { - "closed_at": { - "type": "date" - }, - "closed_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - }, - "created_at": { - "type": "date" - }, - "created_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - }, - "description": { - "type": "text" - }, - "external_service": { - "properties": { - "connector_id": { - "type": "keyword" - }, - "connector_name": { - "type": "keyword" - }, - "external_id": { - "type": "keyword" - }, - "external_title": { - "type": "text" - }, - "external_url": { - "type": "text" - }, - "pushed_at": { - "type": "date" - }, - "pushed_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - } - } - }, - "status": { - "type": "keyword" - }, - "tags": { - "type": "keyword" - }, - "title": { - "type": "keyword" - }, - "updated_at": { - "type": "date" - }, - "updated_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - } - } - }, - "cases-comments": { - "properties": { - "comment": { - "type": "text" - }, - "created_at": { - "type": "date" - }, - "created_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - }, - "pushed_at": { - "type": "date" - }, - "pushed_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - }, - "updated_at": { - "type": "date" - }, - "updated_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - } - } - }, - "cases-configure": { - "properties": { - "closure_type": { - "type": "keyword" - }, - "connector_id": { - "type": "keyword" - }, - "connector_name": { - "type": "keyword" - }, - "created_at": { - "type": "date" - }, - "created_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - }, - "updated_at": { - "type": "date" - }, - "updated_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - } - } - }, - "cases-user-actions": { - "properties": { - "action": { - "type": "keyword" - }, - "action_at": { - "type": "date" - }, - "action_by": { - "properties": { - "email": { - "type": "keyword" - }, - "full_name": { - "type": "keyword" - }, - "username": { - "type": "keyword" - } - } - }, - "action_field": { - "type": "keyword" - }, - "new_value": { - "type": "text" - }, - "old_value": { - "type": "text" - } - } - }, - "config": { - "dynamic": "true", - "properties": { - "accessibility:disableAnimations": { - "type": "boolean" - }, - "buildNum": { - "type": "keyword" - }, - "dateFormat:tz": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "defaultIndex": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "timepicker:quickRanges": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "dashboard": { - "properties": { - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "optionsJSON": { - "type": "text" - }, - "panelsJSON": { - "type": "text" - }, - "refreshInterval": { - "properties": { - "display": { - "type": "keyword" - }, - "pause": { - "type": "boolean" - }, - "section": { - "type": "integer" - }, - "value": { - "type": "integer" - } - } - }, - "timeFrom": { - "type": "keyword" - }, - "timeRestore": { - "type": "boolean" - }, - "timeTo": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "file-upload-telemetry": { - "properties": { - "filesUploadedTotalCount": { - "type": "long" - } - } - }, - "graph-workspace": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "numLinks": { - "type": "integer" - }, - "numVertices": { - "type": "integer" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "wsState": { - "type": "text" - } - } - }, - "index-pattern": { - "properties": { - "fieldFormatMap": { - "type": "text" - }, - "fields": { - "type": "text" - }, - "intervalName": { - "type": "keyword" - }, - "notExpandable": { - "type": "boolean" - }, - "sourceFilters": { - "type": "text" - }, - "timeFieldName": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "type": { - "type": "keyword" - }, - "typeMeta": { - "type": "keyword" - } - } - }, - "infrastructure-ui-source": { - "properties": { - "description": { - "type": "text" - }, - "fields": { - "properties": { - "container": { - "type": "keyword" - }, - "host": { - "type": "keyword" - }, - "pod": { - "type": "keyword" - }, - "tiebreaker": { - "type": "keyword" - }, - "timestamp": { - "type": "keyword" - } - } - }, - "logAlias": { - "type": "keyword" - }, - "logColumns": { - "properties": { - "fieldColumn": { - "properties": { - "field": { - "type": "keyword" - }, - "id": { - "type": "keyword" - } - } - }, - "messageColumn": { - "properties": { - "id": { - "type": "keyword" - } - } - }, - "timestampColumn": { - "properties": { - "id": { - "type": "keyword" - } - } - } - }, - "type": "nested" - }, - "metricAlias": { - "type": "keyword" - }, - "name": { - "type": "text" - } - } - }, - "inventory-view": { - "properties": { - "accountId": { - "type": "keyword" - }, - "autoBounds": { - "type": "boolean" - }, - "autoReload": { - "type": "boolean" - }, - "boundsOverride": { - "properties": { - "max": { - "type": "integer" - }, - "min": { - "type": "integer" - } - } - }, - "customMetrics": { - "properties": { - "aggregation": { - "type": "keyword" - }, - "field": { - "type": "keyword" - }, - "id": { - "type": "keyword" - }, - "label": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - }, - "type": "nested" - }, - "customOptions": { - "properties": { - "field": { - "type": "keyword" - }, - "text": { - "type": "keyword" - } - }, - "type": "nested" - }, - "filterQuery": { - "properties": { - "expression": { - "type": "keyword" - }, - "kind": { - "type": "keyword" - } - } - }, - "groupBy": { - "properties": { - "field": { - "type": "keyword" - }, - "label": { - "type": "keyword" - } - }, - "type": "nested" - }, - "metric": { - "properties": { - "aggregation": { - "type": "keyword" - }, - "field": { - "type": "keyword" - }, - "id": { - "type": "keyword" - }, - "label": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - } - }, - "name": { - "type": "keyword" - }, - "nodeType": { - "type": "keyword" - }, - "region": { - "type": "keyword" - }, - "time": { - "type": "long" - }, - "view": { - "type": "keyword" - } - } - }, - "kql-telemetry": { - "properties": { - "optInCount": { - "type": "long" - }, - "optOutCount": { - "type": "long" - } - } - }, - "lens": { - "properties": { - "expression": { - "index": false, - "type": "keyword" - }, - "state": { - "type": "flattened" - }, - "title": { - "type": "text" - }, - "visualizationType": { - "type": "keyword" - } - } - }, - "lens-ui-telemetry": { - "properties": { - "count": { - "type": "integer" - }, - "date": { - "type": "date" - }, - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - } - }, - "map": { - "properties": { - "bounds": { - "dynamic": false, - "properties": {} - }, - "description": { - "type": "text" - }, - "layerListJSON": { - "type": "text" - }, - "mapStateJSON": { - "type": "text" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "maps-telemetry": { - "properties": { - "attributesPerMap": { - "properties": { - "dataSourcesCount": { - "properties": { - "avg": { - "type": "long" - }, - "max": { - "type": "long" - }, - "min": { - "type": "long" - } - } - }, - "emsVectorLayersCount": { - "dynamic": "true", - "type": "object" - }, - "layerTypesCount": { - "dynamic": "true", - "type": "object" - }, - "layersCount": { - "properties": { - "avg": { - "type": "long" - }, - "max": { - "type": "long" - }, - "min": { - "type": "long" - } - } - } - } - }, - "indexPatternsWithGeoFieldCount": { - "type": "long" - }, - "mapsTotalCount": { - "type": "long" - }, - "settings": { - "properties": { - "showMapVisualizationTypes": { - "type": "boolean" - } - } - }, - "timeCaptured": { - "type": "date" - } - } - }, - "metrics-explorer-view": { - "properties": { - "chartOptions": { - "properties": { - "stack": { - "type": "boolean" - }, - "type": { - "type": "keyword" - }, - "yAxisMode": { - "type": "keyword" - } - } - }, - "currentTimerange": { - "properties": { - "from": { - "type": "keyword" - }, - "interval": { - "type": "keyword" - }, - "to": { - "type": "keyword" - } - } - }, - "name": { - "type": "keyword" - }, - "options": { - "properties": { - "aggregation": { - "type": "keyword" - }, - "filterQuery": { - "type": "keyword" - }, - "groupBy": { - "type": "keyword" - }, - "limit": { - "type": "integer" - }, - "metrics": { - "properties": { - "aggregation": { - "type": "keyword" - }, - "color": { - "type": "keyword" - }, - "field": { - "type": "keyword" - }, - "label": { - "type": "keyword" - } - }, - "type": "nested" - } - } - } - } - }, - "migrationVersion": { - "dynamic": "true", - "properties": { - "index-pattern": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "space": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "ml-telemetry": { - "properties": { - "file_data_visualizer": { - "properties": { - "index_creation_count": { - "type": "long" - } - } - } - } - }, - "namespace": { - "type": "keyword" - }, - "namespaces": { - "type": "keyword" - }, - "query": { - "properties": { - "description": { - "type": "text" - }, - "filters": { - "enabled": false, - "type": "object" - }, - "query": { - "properties": { - "language": { - "type": "keyword" - }, - "query": { - "index": false, - "type": "keyword" - } - } - }, - "timefilter": { - "enabled": false, - "type": "object" - }, - "title": { - "type": "text" - } - } - }, - "references": { - "properties": { - "id": { - "type": "keyword" - }, - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - }, - "type": "nested" - }, - "sample-data-telemetry": { - "properties": { - "installCount": { - "type": "long" - }, - "unInstallCount": { - "type": "long" - } - } - }, - "search": { - "properties": { - "columns": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "sort": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "server": { - "properties": { - "uuid": { - "type": "keyword" - } - } - }, - "siem-detection-engine-rule-actions": { - "properties": { - "actions": { - "properties": { - "action_type_id": { - "type": "keyword" - }, - "group": { - "type": "keyword" - }, - "id": { - "type": "keyword" - }, - "params": { - "enabled": false, - "type": "object" - } - } - }, - "alertThrottle": { - "type": "keyword" - }, - "ruleAlertId": { - "type": "keyword" - }, - "ruleThrottle": { - "type": "keyword" - } - } - }, - "siem-detection-engine-rule-status": { - "properties": { - "alertId": { - "type": "keyword" - }, - "bulkCreateTimeDurations": { - "type": "float" - }, - "gap": { - "type": "text" - }, - "lastFailureAt": { - "type": "date" - }, - "lastFailureMessage": { - "type": "text" - }, - "lastLookBackDate": { - "type": "date" - }, - "lastSuccessAt": { - "type": "date" - }, - "lastSuccessMessage": { - "type": "text" - }, - "searchAfterTimeDurations": { - "type": "float" - }, - "status": { - "type": "keyword" - }, - "statusDate": { - "type": "date" - } - } - }, - "siem-ui-timeline": { - "properties": { - "columns": { - "properties": { - "aggregatable": { - "type": "boolean" - }, - "category": { - "type": "keyword" - }, - "columnHeaderType": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "example": { - "type": "text" - }, - "id": { - "type": "keyword" - }, - "indexes": { - "type": "keyword" - }, - "name": { - "type": "text" - }, - "placeholder": { - "type": "text" - }, - "searchable": { - "type": "boolean" - }, - "type": { - "type": "keyword" - } - } - }, - "created": { - "type": "date" - }, - "createdBy": { - "type": "text" - }, - "dataProviders": { - "properties": { - "and": { - "properties": { - "enabled": { - "type": "boolean" - }, - "excluded": { - "type": "boolean" - }, - "id": { - "type": "keyword" - }, - "kqlQuery": { - "type": "text" - }, - "name": { - "type": "text" - }, - "queryMatch": { - "properties": { - "displayField": { - "type": "text" - }, - "displayValue": { - "type": "text" - }, - "field": { - "type": "text" - }, - "operator": { - "type": "text" - }, - "value": { - "type": "text" - } - } - } - } - }, - "enabled": { - "type": "boolean" - }, - "excluded": { - "type": "boolean" - }, - "id": { - "type": "keyword" - }, - "kqlQuery": { - "type": "text" - }, - "name": { - "type": "text" - }, - "queryMatch": { - "properties": { - "displayField": { - "type": "text" - }, - "displayValue": { - "type": "text" - }, - "field": { - "type": "text" - }, - "operator": { - "type": "text" - }, - "value": { - "type": "text" - } - } - } - } - }, - "dateRange": { - "properties": { - "end": { - "type": "date" - }, - "start": { - "type": "date" - } - } - }, - "description": { - "type": "text" - }, - "eventType": { - "type": "keyword" - }, - "favorite": { - "properties": { - "favoriteDate": { - "type": "date" - }, - "fullName": { - "type": "text" - }, - "keySearch": { - "type": "text" - }, - "userName": { - "type": "text" - } - } - }, - "filters": { - "properties": { - "exists": { - "type": "text" - }, - "match_all": { - "type": "text" - }, - "meta": { - "properties": { - "alias": { - "type": "text" - }, - "controlledBy": { - "type": "text" - }, - "disabled": { - "type": "boolean" - }, - "field": { - "type": "text" - }, - "formattedValue": { - "type": "text" - }, - "index": { - "type": "keyword" - }, - "key": { - "type": "keyword" - }, - "negate": { - "type": "boolean" - }, - "params": { - "type": "text" - }, - "type": { - "type": "keyword" - }, - "value": { - "type": "text" - } - } - }, - "missing": { - "type": "text" - }, - "query": { - "type": "text" - }, - "range": { - "type": "text" - }, - "script": { - "type": "text" - } - } - }, - "kqlMode": { - "type": "keyword" - }, - "kqlQuery": { - "properties": { - "filterQuery": { - "properties": { - "kuery": { - "properties": { - "expression": { - "type": "text" - }, - "kind": { - "type": "keyword" - } - } - }, - "serializedQuery": { - "type": "text" - } - } - } - } - }, - "savedQueryId": { - "type": "keyword" - }, - "sort": { - "properties": { - "columnId": { - "type": "keyword" - }, - "sortDirection": { - "type": "keyword" - } - } - }, - "templateTimelineId": { - "type": "text" - }, - "templateTimelineVersion": { - "type": "integer" - }, - "timelineType": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "updated": { - "type": "date" - }, - "updatedBy": { - "type": "text" - } - } - }, - "siem-ui-timeline-note": { - "properties": { - "created": { - "type": "date" - }, - "createdBy": { - "type": "text" - }, - "eventId": { - "type": "keyword" - }, - "note": { - "type": "text" - }, - "timelineId": { - "type": "keyword" - }, - "updated": { - "type": "date" - }, - "updatedBy": { - "type": "text" - } - } - }, - "siem-ui-timeline-pinned-event": { - "properties": { - "created": { - "type": "date" - }, - "createdBy": { - "type": "text" - }, - "eventId": { - "type": "keyword" - }, - "timelineId": { - "type": "keyword" - }, - "updated": { - "type": "date" - }, - "updatedBy": { - "type": "text" - } - } - }, - "space": { - "properties": { - "_reserved": { - "type": "boolean" - }, - "color": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "disabledFeatures": { - "type": "keyword" - }, - "imageUrl": { - "index": false, - "type": "text" - }, - "initials": { - "type": "keyword" - }, - "name": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "spaceId": { - "type": "keyword" - }, - "telemetry": { - "properties": { - "allowChangingOptInStatus": { - "type": "boolean" - }, - "enabled": { - "type": "boolean" - }, - "lastReported": { - "type": "date" - }, - "lastVersionChecked": { - "type": "keyword" - }, - "reportFailureCount": { - "type": "integer" - }, - "reportFailureVersion": { - "type": "keyword" - }, - "sendUsageFrom": { - "type": "keyword" - }, - "userHasSeenNotice": { - "type": "boolean" - } - } - }, - "tsvb-validation-telemetry": { - "properties": { - "failedRequests": { - "type": "long" - } - } - }, - "type": { - "type": "keyword" - }, - "ui-metric": { - "properties": { - "count": { - "type": "integer" - } - } - }, - "updated_at": { - "type": "date" - }, - "upgrade-assistant-reindex-operation": { - "properties": { - "errorMessage": { - "type": "keyword" - }, - "indexName": { - "type": "keyword" - }, - "lastCompletedStep": { - "type": "integer" - }, - "locked": { - "type": "date" - }, - "newIndexName": { - "type": "keyword" - }, - "reindexOptions": { - "properties": { - "openAndClose": { - "type": "boolean" - }, - "queueSettings": { - "properties": { - "queuedAt": { - "type": "long" - }, - "startedAt": { - "type": "long" - } - } - } - } - }, - "reindexTaskId": { - "type": "keyword" - }, - "reindexTaskPercComplete": { - "type": "float" - }, - "runningReindexCount": { - "type": "integer" - }, - "status": { - "type": "integer" - } - } - }, - "upgrade-assistant-telemetry": { - "properties": { - "features": { - "properties": { - "deprecation_logging": { - "properties": { - "enabled": { - "null_value": true, - "type": "boolean" - } - } - } - } - }, - "ui_open": { - "properties": { - "cluster": { - "null_value": 0, - "type": "long" - }, - "indices": { - "null_value": 0, - "type": "long" - }, - "overview": { - "null_value": 0, - "type": "long" - } - } - }, - "ui_reindex": { - "properties": { - "close": { - "null_value": 0, - "type": "long" - }, - "open": { - "null_value": 0, - "type": "long" - }, - "start": { - "null_value": 0, - "type": "long" - }, - "stop": { - "null_value": 0, - "type": "long" - } - } - } - } - }, - "uptime-dynamic-settings": { - "properties": { - "certThresholds": { - "properties": { - "age": { - "type": "long" - }, - "expiration": { - "type": "long" - } - } - }, - "heartbeatIndices": { - "type": "keyword" - } - } - }, - "url": { - "properties": { - "accessCount": { - "type": "long" - }, - "accessDate": { - "type": "date" - }, - "createDate": { - "type": "date" - }, - "url": { - "fields": { - "keyword": { - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "visualization": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "savedSearchRefName": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "visState": { - "type": "text" - } - } - } - } - }, - "settings": { - "index": { - "auto_expand_replicas": "0-1", - "number_of_replicas": "0", - "number_of_shards": "1" - } - } - } -} diff --git a/x-pack/test/functional/es_archives/lens/reporting/data.json.gz b/x-pack/test/functional/es_archives/lens/reporting/data.json.gz deleted file mode 100644 index 3c06824f60646..0000000000000 Binary files a/x-pack/test/functional/es_archives/lens/reporting/data.json.gz and /dev/null differ diff --git a/x-pack/test/functional/es_archives/lens/reporting/mappings.json b/x-pack/test/functional/es_archives/lens/reporting/mappings.json deleted file mode 100644 index 907c5ee4fe70a..0000000000000 --- a/x-pack/test/functional/es_archives/lens/reporting/mappings.json +++ /dev/null @@ -1,1261 +0,0 @@ -{ - "type": "index", - "value": { - "aliases": { - ".kibana": { - } - }, - "index": ".kibana_1", - "mappings": { - "_meta": { - "migrationMappingPropertyHashes": { - "apm-telemetry": "07ee1939fa4302c62ddc052ec03fed90", - "canvas-element": "7390014e1091044523666d97247392fc", - "canvas-workpad": "b0a1706d356228dbdcb4a17e6b9eb231", - "config": "87aca8fdb053154f11383fce3dbf3edf", - "dashboard": "d00f614b29a80360e1190193fd333bab", - "file-upload-telemetry": "0ed4d3e1983d1217a30982630897092e", - "graph-workspace": "cd7ba1330e6682e9cc00b78850874be1", - "index-pattern": "66eccb05066c5a89924f48a9e9736499", - "infrastructure-ui-source": "ddc0ecb18383f6b26101a2fadb2dab0c", - "inventory-view": "84b320fd67209906333ffce261128462", - "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", - "lens": "21c3ea0763beb1ecb0162529706b88c5", - "maps-telemetry": "a4229f8b16a6820c6d724b7e0c1f729d", - "metrics-explorer-view": "53c5365793677328df0ccb6138bf3cdd", - "migrationVersion": "4a1746014a75ade3a714e1db5763276f", - "ml-telemetry": "257fd1d4b4fdbb9cb4b8a3b27da201e9", - "namespace": "2f4316de49999235636386fe51dc06c1", - "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9", - "references": "7997cf5a56cc02bdc9c93361bde732b0", - "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", - "search": "181661168bbadd1eff5902361e2a0d5c", - "server": "ec97f1c5da1a19609a60874e5af1100c", - "siem-ui-timeline": "1f6f0860ad7bc0dba3e42467ca40470d", - "siem-ui-timeline-note": "8874706eedc49059d4cf0f5094559084", - "siem-ui-timeline-pinned-event": "20638091112f0e14f0e443d512301c29", - "space": "c5ca8acafa0beaa4d08d014a97b6bc6b", - "telemetry": "e1c8bc94e443aefd9458932cc0697a4d", - "type": "2f4316de49999235636386fe51dc06c1", - "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3", - "updated_at": "00da57df13e94e9d98437d13ace4bfe0", - "upgrade-assistant-reindex-operation": "a53a20fe086b72c9a86da3cc12dad8a6", - "upgrade-assistant-telemetry": "56702cec857e0a9dacfb696655b4ff7b", - "url": "c7f66a0df8b1b52f17c28c4adb111105", - "visualization": "52d7a13ad68a150c4525b292d23e12cc" - } - }, - "dynamic": "strict", - "properties": { - "action": { - "properties": { - "actionTypeId": { - "type": "keyword" - }, - "config": { - "enabled": false, - "type": "object" - }, - "description": { - "type": "text" - }, - "secrets": { - "type": "binary" - } - } - }, - "action_task_params": { - "properties": { - "actionId": { - "type": "keyword" - }, - "apiKey": { - "type": "binary" - }, - "params": { - "enabled": false, - "type": "object" - } - } - }, - "alert": { - "properties": { - "actions": { - "properties": { - "actionRef": { - "type": "keyword" - }, - "group": { - "type": "keyword" - }, - "params": { - "enabled": false, - "type": "object" - } - }, - "type": "nested" - }, - "alertTypeId": { - "type": "keyword" - }, - "params": { - "enabled": false, - "type": "object" - }, - "apiKey": { - "type": "binary" - }, - "apiKeyOwner": { - "type": "keyword" - }, - "createdBy": { - "type": "keyword" - }, - "enabled": { - "type": "boolean" - }, - "interval": { - "type": "keyword" - }, - "scheduledTaskId": { - "type": "keyword" - }, - "updatedBy": { - "type": "keyword" - } - } - }, - "apm-telemetry": { - "properties": { - "has_any_services": { - "type": "boolean" - }, - "services_per_agent": { - "properties": { - "dotnet": { - "null_value": 0, - "type": "long" - }, - "go": { - "null_value": 0, - "type": "long" - }, - "java": { - "null_value": 0, - "type": "long" - }, - "js-base": { - "null_value": 0, - "type": "long" - }, - "nodejs": { - "null_value": 0, - "type": "long" - }, - "python": { - "null_value": 0, - "type": "long" - }, - "ruby": { - "null_value": 0, - "type": "long" - }, - "rum-js": { - "null_value": 0, - "type": "long" - } - } - } - } - }, - "canvas-element": { - "dynamic": "false", - "properties": { - "@created": { - "type": "date" - }, - "@timestamp": { - "type": "date" - }, - "content": { - "type": "text" - }, - "help": { - "type": "text" - }, - "image": { - "type": "text" - }, - "name": { - "fields": { - "keyword": { - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "canvas-workpad": { - "dynamic": "false", - "properties": { - "@created": { - "type": "date" - }, - "@timestamp": { - "type": "date" - }, - "name": { - "fields": { - "keyword": { - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "config": { - "dynamic": "true", - "properties": { - "accessibility:disableAnimations": { - "type": "boolean" - }, - "buildNum": { - "type": "keyword" - }, - "dateFormat:tz": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "defaultIndex": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "dashboard": { - "properties": { - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "optionsJSON": { - "type": "text" - }, - "panelsJSON": { - "type": "text" - }, - "refreshInterval": { - "properties": { - "display": { - "type": "keyword" - }, - "pause": { - "type": "boolean" - }, - "section": { - "type": "integer" - }, - "value": { - "type": "integer" - } - } - }, - "timeFrom": { - "type": "keyword" - }, - "timeRestore": { - "type": "boolean" - }, - "timeTo": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "file-upload-telemetry": { - "properties": { - "filesUploadedTotalCount": { - "type": "long" - } - } - }, - "gis-map": { - "properties": { - "bounds": { - "dynamic": false, - "properties": {} - }, - "description": { - "type": "text" - }, - "layerListJSON": { - "type": "text" - }, - "mapStateJSON": { - "type": "text" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "graph-workspace": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "numLinks": { - "type": "integer" - }, - "numVertices": { - "type": "integer" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "wsState": { - "type": "text" - } - } - }, - "index-pattern": { - "properties": { - "fieldFormatMap": { - "type": "text" - }, - "fields": { - "type": "text" - }, - "intervalName": { - "type": "keyword" - }, - "notExpandable": { - "type": "boolean" - }, - "sourceFilters": { - "type": "text" - }, - "timeFieldName": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "type": { - "type": "keyword" - }, - "typeMeta": { - "type": "keyword" - } - } - }, - "infrastructure-ui-source": { - "properties": { - "description": { - "type": "text" - }, - "fields": { - "properties": { - "container": { - "type": "keyword" - }, - "host": { - "type": "keyword" - }, - "pod": { - "type": "keyword" - }, - "tiebreaker": { - "type": "keyword" - }, - "timestamp": { - "type": "keyword" - } - } - }, - "logAlias": { - "type": "keyword" - }, - "logColumns": { - "properties": { - "fieldColumn": { - "properties": { - "field": { - "type": "keyword" - }, - "id": { - "type": "keyword" - } - } - }, - "messageColumn": { - "properties": { - "id": { - "type": "keyword" - } - } - }, - "timestampColumn": { - "properties": { - "id": { - "type": "keyword" - } - } - } - }, - "type": "nested" - }, - "metricAlias": { - "type": "keyword" - }, - "name": { - "type": "text" - } - } - }, - "inventory-view": { - "properties": { - "autoBounds": { - "type": "boolean" - }, - "autoReload": { - "type": "boolean" - }, - "boundsOverride": { - "properties": { - "max": { - "type": "integer" - }, - "min": { - "type": "integer" - } - } - }, - "customOptions": { - "properties": { - "field": { - "type": "keyword" - }, - "text": { - "type": "keyword" - } - }, - "type": "nested" - }, - "filterQuery": { - "properties": { - "expression": { - "type": "keyword" - }, - "kind": { - "type": "keyword" - } - } - }, - "groupBy": { - "properties": { - "field": { - "type": "keyword" - }, - "label": { - "type": "keyword" - } - }, - "type": "nested" - }, - "metric": { - "properties": { - "type": { - "type": "keyword" - } - } - }, - "name": { - "type": "keyword" - }, - "nodeType": { - "type": "keyword" - }, - "time": { - "type": "integer" - }, - "view": { - "type": "keyword" - } - } - }, - "kql-telemetry": { - "properties": { - "optInCount": { - "type": "long" - }, - "optOutCount": { - "type": "long" - } - } - }, - "lens": { - "properties": { - "expression": { - "index": false, - "type": "keyword" - }, - "state": { - "type": "flattened" - }, - "title": { - "type": "text" - }, - "visualizationType": { - "type": "keyword" - } - } - }, - "map": { - "properties": { - "bounds": { - "dynamic": false, - "properties": {} - }, - "description": { - "type": "text" - }, - "layerListJSON": { - "type": "text" - }, - "mapStateJSON": { - "type": "text" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "maps-telemetry": { - "properties": { - "attributesPerMap": { - "properties": { - "dataSourcesCount": { - "properties": { - "avg": { - "type": "long" - }, - "max": { - "type": "long" - }, - "min": { - "type": "long" - } - } - }, - "emsVectorLayersCount": { - "dynamic": "true", - "type": "object" - }, - "layerTypesCount": { - "dynamic": "true", - "type": "object" - }, - "layersCount": { - "properties": { - "avg": { - "type": "long" - }, - "max": { - "type": "long" - }, - "min": { - "type": "long" - } - } - } - } - }, - "mapsTotalCount": { - "type": "long" - }, - "timeCaptured": { - "type": "date" - } - } - }, - "metrics-explorer-view": { - "properties": { - "chartOptions": { - "properties": { - "stack": { - "type": "boolean" - }, - "type": { - "type": "keyword" - }, - "yAxisMode": { - "type": "keyword" - } - } - }, - "currentTimerange": { - "properties": { - "from": { - "type": "keyword" - }, - "interval": { - "type": "keyword" - }, - "to": { - "type": "keyword" - } - } - }, - "name": { - "type": "keyword" - }, - "options": { - "properties": { - "aggregation": { - "type": "keyword" - }, - "filterQuery": { - "type": "keyword" - }, - "groupBy": { - "type": "keyword" - }, - "limit": { - "type": "integer" - }, - "metrics": { - "properties": { - "aggregation": { - "type": "keyword" - }, - "color": { - "type": "keyword" - }, - "field": { - "type": "keyword" - }, - "label": { - "type": "keyword" - } - }, - "type": "nested" - } - } - } - } - }, - "migrationVersion": { - "dynamic": "true", - "properties": { - "dashboard": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "index-pattern": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "space": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "visualization": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "ml-telemetry": { - "properties": { - "file_data_visualizer": { - "properties": { - "index_creation_count": { - "type": "long" - } - } - } - } - }, - "namespace": { - "type": "keyword" - }, - "query": { - "properties": { - "description": { - "type": "text" - }, - "filters": { - "enabled": false, - "type": "object" - }, - "query": { - "properties": { - "language": { - "type": "keyword" - }, - "query": { - "index": false, - "type": "keyword" - } - } - }, - "timefilter": { - "enabled": false, - "type": "object" - }, - "title": { - "type": "text" - } - } - }, - "references": { - "properties": { - "id": { - "type": "keyword" - }, - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - } - }, - "type": "nested" - }, - "sample-data-telemetry": { - "properties": { - "installCount": { - "type": "long" - }, - "unInstallCount": { - "type": "long" - } - } - }, - "search": { - "properties": { - "columns": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "sort": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "server": { - "properties": { - "uuid": { - "type": "keyword" - } - } - }, - "siem-ui-timeline": { - "properties": { - "columns": { - "properties": { - "aggregatable": { - "type": "boolean" - }, - "category": { - "type": "keyword" - }, - "columnHeaderType": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "example": { - "type": "text" - }, - "id": { - "type": "keyword" - }, - "indexes": { - "type": "keyword" - }, - "name": { - "type": "text" - }, - "placeholder": { - "type": "text" - }, - "searchable": { - "type": "boolean" - }, - "type": { - "type": "keyword" - } - } - }, - "created": { - "type": "date" - }, - "createdBy": { - "type": "text" - }, - "dataProviders": { - "properties": { - "and": { - "properties": { - "enabled": { - "type": "boolean" - }, - "excluded": { - "type": "boolean" - }, - "id": { - "type": "keyword" - }, - "kqlQuery": { - "type": "text" - }, - "name": { - "type": "text" - }, - "queryMatch": { - "properties": { - "displayField": { - "type": "text" - }, - "displayValue": { - "type": "text" - }, - "field": { - "type": "text" - }, - "operator": { - "type": "text" - }, - "value": { - "type": "text" - } - } - } - } - }, - "enabled": { - "type": "boolean" - }, - "excluded": { - "type": "boolean" - }, - "id": { - "type": "keyword" - }, - "kqlQuery": { - "type": "text" - }, - "name": { - "type": "text" - }, - "queryMatch": { - "properties": { - "displayField": { - "type": "text" - }, - "displayValue": { - "type": "text" - }, - "field": { - "type": "text" - }, - "operator": { - "type": "text" - }, - "value": { - "type": "text" - } - } - } - } - }, - "dateRange": { - "properties": { - "end": { - "type": "date" - }, - "start": { - "type": "date" - } - } - }, - "description": { - "type": "text" - }, - "favorite": { - "properties": { - "favoriteDate": { - "type": "date" - }, - "fullName": { - "type": "text" - }, - "keySearch": { - "type": "text" - }, - "userName": { - "type": "text" - } - } - }, - "kqlMode": { - "type": "keyword" - }, - "kqlQuery": { - "properties": { - "filterQuery": { - "properties": { - "kuery": { - "properties": { - "expression": { - "type": "text" - }, - "kind": { - "type": "keyword" - } - } - }, - "serializedQuery": { - "type": "text" - } - } - } - } - }, - "sort": { - "properties": { - "columnId": { - "type": "keyword" - }, - "sortDirection": { - "type": "keyword" - } - } - }, - "title": { - "type": "text" - }, - "updated": { - "type": "date" - }, - "updatedBy": { - "type": "text" - } - } - }, - "siem-ui-timeline-note": { - "properties": { - "created": { - "type": "date" - }, - "createdBy": { - "type": "text" - }, - "eventId": { - "type": "keyword" - }, - "note": { - "type": "text" - }, - "timelineId": { - "type": "keyword" - }, - "updated": { - "type": "date" - }, - "updatedBy": { - "type": "text" - } - } - }, - "siem-ui-timeline-pinned-event": { - "properties": { - "created": { - "type": "date" - }, - "createdBy": { - "type": "text" - }, - "eventId": { - "type": "keyword" - }, - "timelineId": { - "type": "keyword" - }, - "updated": { - "type": "date" - }, - "updatedBy": { - "type": "text" - } - } - }, - "space": { - "properties": { - "_reserved": { - "type": "boolean" - }, - "color": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "disabledFeatures": { - "type": "keyword" - }, - "imageUrl": { - "index": false, - "type": "text" - }, - "initials": { - "type": "keyword" - }, - "name": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "spaceId": { - "type": "keyword" - }, - "telemetry": { - "properties": { - "enabled": { - "type": "boolean" - } - } - }, - "type": { - "type": "keyword" - }, - "ui-metric": { - "properties": { - "count": { - "type": "integer" - } - } - }, - "updated_at": { - "type": "date" - }, - "upgrade-assistant-reindex-operation": { - "dynamic": "true", - "properties": { - "indexName": { - "type": "keyword" - }, - "status": { - "type": "integer" - } - } - }, - "upgrade-assistant-telemetry": { - "properties": { - "features": { - "properties": { - "deprecation_logging": { - "properties": { - "enabled": { - "null_value": true, - "type": "boolean" - } - } - } - } - }, - "ui_open": { - "properties": { - "cluster": { - "null_value": 0, - "type": "long" - }, - "indices": { - "null_value": 0, - "type": "long" - }, - "overview": { - "null_value": 0, - "type": "long" - } - } - }, - "ui_reindex": { - "properties": { - "close": { - "null_value": 0, - "type": "long" - }, - "open": { - "null_value": 0, - "type": "long" - }, - "start": { - "null_value": 0, - "type": "long" - }, - "stop": { - "null_value": 0, - "type": "long" - } - } - } - } - }, - "url": { - "properties": { - "accessCount": { - "type": "long" - }, - "accessDate": { - "type": "date" - }, - "createDate": { - "type": "date" - }, - "url": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "visualization": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "savedSearchRefName": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "visState": { - "type": "text" - } - } - } - } - }, - "settings": { - "index": { - "auto_expand_replicas": "0-1", - "number_of_replicas": "0", - "number_of_shards": "1" - } - } - } -} diff --git a/x-pack/test/functional/es_archives/security_solution/runtime/mappings.json b/x-pack/test/functional/es_archives/security_solution/runtime/mappings.json index 33235d0171837..8fde854cb3b89 100644 --- a/x-pack/test/functional/es_archives/security_solution/runtime/mappings.json +++ b/x-pack/test/functional/es_archives/security_solution/runtime/mappings.json @@ -10,7 +10,7007 @@ "script": { "source": "emit(doc['host.name'].value)" } - } + }, + "my-runtime-field-6999": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6998": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6997": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6996": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6995": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6994": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6993": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6992": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6991": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6990": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6989": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6988": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6987": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6986": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6985": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6984": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6983": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6982": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6981": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6980": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6979": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6978": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6977": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6976": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6975": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6974": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6973": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6972": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6971": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6970": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6969": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6968": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6967": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6966": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6965": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6964": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6963": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6962": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6961": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6960": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6959": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6958": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6957": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6956": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6955": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6954": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6953": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6952": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6951": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6950": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6949": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6948": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6947": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6946": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6945": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6944": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6943": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6942": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6941": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6940": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6939": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6938": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6937": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6936": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6935": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6934": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6933": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6932": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6931": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6930": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6929": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6928": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6927": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6926": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6925": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6924": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6923": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6922": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6921": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6920": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6919": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6918": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6917": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6916": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6915": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6914": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6913": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6912": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6911": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6910": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6909": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6908": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6907": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6906": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6905": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6904": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6903": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6902": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6901": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6900": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6899": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6898": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6897": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6896": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6895": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6894": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6893": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6892": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6891": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6890": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6889": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6888": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6887": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6886": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6885": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6884": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6883": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6882": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6881": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6880": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6879": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6878": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6877": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6876": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6875": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6874": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6873": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6872": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6871": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6870": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6869": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6868": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6867": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6866": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6865": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6864": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6863": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6862": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6861": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6860": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6859": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6858": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6857": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6856": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6855": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6854": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6853": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6852": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6851": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6850": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6849": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6848": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6847": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6846": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6845": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6844": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6843": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6842": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6841": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6840": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6839": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6838": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6837": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6836": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6835": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6834": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6833": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6832": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6831": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6830": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6829": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6828": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6827": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6826": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6825": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6824": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6823": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6822": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6821": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6820": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6819": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6818": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6817": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6816": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6815": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6814": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6813": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6812": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6811": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6810": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6809": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6808": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6807": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6806": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6805": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6804": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6803": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6802": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6801": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6800": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6799": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6798": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6797": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6796": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6795": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6794": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6793": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6792": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6791": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6790": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6789": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6788": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6787": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6786": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6785": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6784": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6783": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6782": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6781": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6780": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6779": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6778": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6777": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6776": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6775": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6774": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6773": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6772": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6771": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6770": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6769": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6768": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6767": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6766": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6765": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6764": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6763": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6762": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6761": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6760": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6759": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6758": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6757": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6756": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6755": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6754": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6753": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6752": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6751": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6750": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6749": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6748": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6747": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6746": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6745": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6744": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6743": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6742": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6741": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6740": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6739": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6738": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6737": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6736": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6735": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6734": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6733": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6732": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6731": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6730": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6729": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6728": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6727": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6726": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6725": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6724": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6723": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6722": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6721": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6720": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6719": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6718": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6717": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6716": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6715": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6714": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6713": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6712": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6711": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6710": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6709": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6708": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6707": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6706": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6705": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6704": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6703": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6702": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6701": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6700": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6699": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6698": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6697": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6696": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6695": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6694": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6693": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6692": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6691": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6690": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6689": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6688": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6687": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6686": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6685": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6684": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6683": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6682": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6681": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6680": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6679": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6678": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6677": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6676": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6675": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6674": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6673": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6672": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6671": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6670": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6669": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6668": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6667": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6666": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6665": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6664": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6663": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6662": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6661": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6660": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6659": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6658": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6657": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6656": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6655": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6654": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6653": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6652": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6651": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6650": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6649": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6648": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6647": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6646": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6645": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6644": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6643": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6642": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6641": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6640": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6639": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6638": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6637": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6636": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6635": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6634": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6633": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6632": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6631": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6630": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6629": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6628": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6627": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6626": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6625": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6624": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6623": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6622": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6621": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6620": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6619": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6618": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6617": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6616": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6615": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6614": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6613": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6612": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6611": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6610": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6609": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6608": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6607": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6606": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6605": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6604": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6603": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6602": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6601": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6600": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6599": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6598": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6597": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6596": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6595": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6594": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6593": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6592": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6591": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6590": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6589": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6588": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6587": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6586": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6585": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6584": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6583": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6582": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6581": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6580": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6579": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6578": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6577": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6576": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6575": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6574": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6573": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6572": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6571": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6570": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6569": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6568": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6567": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6566": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6565": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6564": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6563": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6562": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6561": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6560": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6559": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6558": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6557": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6556": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6555": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6554": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6553": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6552": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6551": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6550": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6549": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6548": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6547": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6546": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6545": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6544": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6543": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6542": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6541": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6540": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6539": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6538": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6537": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6536": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6535": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6534": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6533": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6532": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6531": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6530": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6529": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6528": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6527": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6526": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6525": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6524": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6523": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6522": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6521": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6520": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6519": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6518": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6517": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6516": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6515": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6514": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6513": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6512": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6511": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6510": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6509": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6508": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6507": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6506": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6505": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6504": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6503": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6502": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6501": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6500": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6499": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6498": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6497": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6496": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6495": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6494": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6493": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6492": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6491": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6490": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6489": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6488": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6487": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6486": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6485": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6484": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6483": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6482": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6481": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6480": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6479": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6478": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6477": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6476": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6475": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6474": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6473": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6472": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6471": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6470": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6469": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6468": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6467": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6466": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6465": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6464": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6463": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6462": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6461": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6460": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6459": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6458": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6457": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6456": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6455": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6454": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6453": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6452": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6451": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6450": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6449": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6448": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6447": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6446": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6445": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6444": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6443": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6442": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6441": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6440": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6439": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6438": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6437": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6436": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6435": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6434": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6433": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6432": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6431": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6430": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6429": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6428": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6427": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6426": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6425": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6424": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6423": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6422": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6421": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6420": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6419": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6418": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6417": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6416": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6415": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6414": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6413": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6412": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6411": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6410": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6409": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6408": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6407": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6406": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6405": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6404": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6403": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6402": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6401": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6400": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6399": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6398": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6397": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6396": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6395": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6394": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6393": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6392": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6391": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6390": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6389": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6388": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6387": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6386": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6385": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6384": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6383": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6382": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6381": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6380": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6379": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6378": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6377": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6376": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6375": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6374": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6373": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6372": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6371": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6370": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6369": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6368": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6367": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6366": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6365": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6364": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6363": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6362": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6361": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6360": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6359": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6358": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6357": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6356": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6355": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6354": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6353": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6352": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6351": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6350": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6349": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6348": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6347": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6346": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6345": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6344": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6343": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6342": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6341": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6340": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6339": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6338": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6337": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6336": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6335": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6334": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6333": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6332": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6331": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6330": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6329": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6328": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6327": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6326": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6325": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6324": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6323": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6322": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6321": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6320": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6319": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6318": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6317": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6316": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6315": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6314": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6313": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6312": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6311": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6310": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6309": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6308": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6307": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6306": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6305": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6304": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6303": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6302": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6301": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6300": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6299": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6298": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6297": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6296": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6295": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6294": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6293": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6292": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6291": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6290": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6289": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6288": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6287": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6286": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6285": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6284": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6283": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6282": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6281": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6280": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6279": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6278": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6277": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6276": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6275": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6274": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6273": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6272": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6271": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6270": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6269": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6268": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6267": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6266": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6265": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6264": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6263": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6262": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6261": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6260": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6259": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6258": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6257": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6256": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6255": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6254": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6253": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6252": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6251": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6250": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6249": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6248": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6247": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6246": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6245": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6244": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6243": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6242": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6241": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6240": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6239": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6238": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6237": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6236": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6235": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6234": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6233": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6232": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6231": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6230": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6229": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6228": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6227": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6226": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6225": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6224": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6223": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6222": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6221": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6220": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6219": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6218": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6217": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6216": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6215": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6214": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6213": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6212": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6211": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6210": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6209": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6208": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6207": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6206": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6205": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6204": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6203": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6202": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6201": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6200": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6199": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6198": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6197": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6196": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6195": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6194": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6193": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6192": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6191": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6190": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6189": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6188": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6187": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6186": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6185": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6184": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6183": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6182": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6181": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6180": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6179": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6178": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6177": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6176": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6175": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6174": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6173": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6172": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6171": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6170": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6169": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6168": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6167": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6166": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6165": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6164": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6163": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6162": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6161": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6160": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6159": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6158": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6157": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6156": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6155": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6154": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6153": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6152": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6151": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6150": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6149": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6148": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6147": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6146": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6145": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6144": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6143": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6142": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6141": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6140": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6139": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6138": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6137": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6136": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6135": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6134": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6133": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6132": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6131": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6130": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6129": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6128": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6127": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6126": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6125": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6124": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6123": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6122": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6121": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6120": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6119": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6118": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6117": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6116": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6115": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6114": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6113": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6112": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6111": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6110": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6109": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6108": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6107": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6106": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6105": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6104": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6103": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6102": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6101": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6100": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6099": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6098": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6097": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6096": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6095": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6094": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6093": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6092": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6091": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6090": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6089": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6088": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6087": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6086": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6085": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6084": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6083": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6082": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6081": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6080": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6079": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6078": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6077": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6076": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6075": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6074": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6073": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6072": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6071": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6070": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6069": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6068": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6067": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6066": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6065": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6064": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6063": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6062": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6061": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6060": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6059": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6058": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6057": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6056": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6055": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6054": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6053": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6052": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6051": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6050": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6049": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6048": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6047": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6046": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6045": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6044": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6043": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6042": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6041": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6040": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6039": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6038": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6037": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6036": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6035": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6034": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6033": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6032": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6031": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6030": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6029": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6028": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6027": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6026": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6025": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6024": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6023": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6022": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6021": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6020": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6019": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6018": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6017": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6016": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6015": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6014": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6013": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6012": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6011": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6010": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6009": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6008": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6007": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6006": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6005": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6004": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6003": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6002": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6001": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6000": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5999": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5998": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5997": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5996": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5995": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5994": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5993": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5992": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5991": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5990": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5989": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5988": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5987": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5986": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5985": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5984": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5983": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5982": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5981": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5980": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5979": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5978": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5977": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5976": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5975": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5974": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5973": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5972": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5971": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5970": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5969": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5968": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5967": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5966": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5965": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5964": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5963": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5962": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5961": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5960": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5959": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5958": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5957": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5956": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5955": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5954": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5953": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5952": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5951": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5950": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5949": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5948": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5947": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5946": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5945": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5944": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5943": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5942": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5941": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5940": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5939": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5938": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5937": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5936": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5935": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5934": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5933": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5932": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5931": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5930": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5929": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5928": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5927": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5926": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5925": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5924": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5923": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5922": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5921": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5920": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5919": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5918": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5917": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5916": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5915": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5914": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5913": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5912": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5911": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5910": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5909": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5908": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5907": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5906": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5905": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5904": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5903": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5902": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5901": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5900": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5899": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5898": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5897": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5896": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5895": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5894": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5893": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5892": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5891": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5890": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5889": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5888": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5887": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5886": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5885": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5884": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5883": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5882": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5881": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5880": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5879": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5878": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5877": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5876": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5875": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5874": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5873": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5872": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5871": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5870": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5869": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5868": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5867": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5866": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5865": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5864": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5863": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5862": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5861": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5860": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5859": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5858": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5857": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5856": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5855": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5854": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5853": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5852": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5851": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5850": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5849": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5848": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5847": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5846": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5845": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5844": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5843": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5842": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5841": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5840": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5839": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5838": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5837": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5836": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5835": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5834": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5833": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5832": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5831": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5830": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5829": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5828": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5827": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5826": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5825": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5824": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5823": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5822": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5821": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5820": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5819": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5818": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5817": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5816": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5815": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5814": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5813": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5812": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5811": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5810": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5809": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5808": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5807": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5806": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5805": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5804": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5803": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5802": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5801": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5800": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5799": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5798": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5797": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5796": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5795": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5794": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5793": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5792": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5791": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5790": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5789": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5788": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5787": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5786": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5785": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5784": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5783": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5782": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5781": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5780": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5779": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5778": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5777": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5776": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5775": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5774": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5773": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5772": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5771": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5770": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5769": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5768": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5767": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5766": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5765": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5764": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5763": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5762": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5761": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5760": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5759": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5758": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5757": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5756": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5755": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5754": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5753": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5752": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5751": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5750": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5749": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5748": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5747": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5746": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5745": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5744": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5743": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5742": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5741": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5740": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5739": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5738": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5737": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5736": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5735": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5734": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5733": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5732": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5731": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5730": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5729": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5728": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5727": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5726": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5725": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5724": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5723": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5722": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5721": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5720": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5719": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5718": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5717": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5716": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5715": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5714": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5713": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5712": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5711": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5710": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5709": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5708": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5707": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5706": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5705": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5704": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5703": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5702": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5701": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5700": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5699": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5698": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5697": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5696": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5695": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5694": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5693": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5692": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5691": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5690": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5689": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5688": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5687": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5686": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5685": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5684": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5683": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5682": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5681": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5680": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5679": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5678": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5677": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5676": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5675": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5674": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5673": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5672": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5671": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5670": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5669": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5668": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5667": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5666": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5665": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5664": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5663": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5662": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5661": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5660": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5659": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5658": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5657": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5656": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5655": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5654": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5653": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5652": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5651": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5650": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5649": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5648": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5647": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5646": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5645": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5644": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5643": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5642": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5641": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5640": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5639": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5638": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5637": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5636": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5635": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5634": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5633": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5632": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5631": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5630": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5629": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5628": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5627": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5626": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5625": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5624": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5623": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5622": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5621": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5620": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5619": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5618": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5617": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5616": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5615": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5614": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5613": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5612": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5611": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5610": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5609": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5608": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5607": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5606": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5605": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5604": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5603": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5602": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5601": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5600": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5599": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5598": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5597": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5596": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5595": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5594": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5593": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5592": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5591": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5590": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5589": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5588": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5587": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5586": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5585": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5584": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5583": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5582": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5581": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5580": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5579": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5578": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5577": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5576": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5575": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5574": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5573": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5572": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5571": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5570": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5569": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5568": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5567": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5566": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5565": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5564": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5563": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5562": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5561": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5560": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5559": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5558": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5557": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5556": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5555": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5554": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5553": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5552": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5551": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5550": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5549": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5548": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5547": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5546": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5545": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5544": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5543": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5542": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5541": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5540": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5539": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5538": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5537": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5536": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5535": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5534": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5533": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5532": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5531": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5530": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5529": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5528": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5527": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5526": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5525": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5524": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5523": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5522": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5521": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5520": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5519": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5518": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5517": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5516": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5515": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5514": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5513": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5512": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5511": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5510": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5509": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5508": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5507": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5506": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5505": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5504": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5503": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5502": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5501": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5500": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5499": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5498": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5497": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5496": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5495": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5494": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5493": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5492": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5491": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5490": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5489": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5488": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5487": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5486": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5485": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5484": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5483": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5482": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5481": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5480": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5479": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5478": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5477": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5476": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5475": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5474": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5473": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5472": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5471": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5470": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5469": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5468": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5467": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5466": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5465": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5464": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5463": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5462": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5461": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5460": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5459": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5458": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5457": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5456": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5455": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5454": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5453": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5452": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5451": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5450": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5449": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5448": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5447": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5446": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5445": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5444": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5443": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5442": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5441": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5440": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5439": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5438": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5437": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5436": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5435": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5434": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5433": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5432": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5431": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5430": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5429": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5428": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5427": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5426": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5425": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5424": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5423": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5422": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5421": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5420": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5419": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5418": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5417": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5416": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5415": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5414": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5413": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5412": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5411": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5410": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5409": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5408": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5407": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5406": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5405": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5404": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5403": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5402": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5401": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5400": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5399": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5398": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5397": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5396": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5395": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5394": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5393": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5392": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5391": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5390": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5389": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5388": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5387": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5386": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5385": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5384": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5383": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5382": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5381": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5380": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5379": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5378": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5377": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5376": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5375": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5374": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5373": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5372": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5371": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5370": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5369": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5368": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5367": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5366": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5365": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5364": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5363": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5362": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5361": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5360": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5359": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5358": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5357": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5356": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5355": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5354": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5353": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5352": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5351": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5350": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5349": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5348": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5347": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5346": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5345": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5344": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5343": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5342": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5341": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5340": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5339": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5338": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5337": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5336": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5335": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5334": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5333": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5332": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5331": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5330": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5329": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5328": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5327": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5326": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5325": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5324": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5323": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5322": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5321": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5320": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5319": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5318": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5317": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5316": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5315": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5314": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5313": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5312": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5311": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5310": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5309": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5308": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5307": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5306": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5305": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5304": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5303": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5302": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5301": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5300": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5299": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5298": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5297": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5296": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5295": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5294": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5293": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5292": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5291": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5290": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5289": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5288": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5287": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5286": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5285": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5284": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5283": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5282": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5281": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5280": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5279": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5278": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5277": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5276": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5275": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5274": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5273": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5272": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5271": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5270": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5269": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5268": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5267": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5266": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5265": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5264": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5263": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5262": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5261": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5260": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5259": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5258": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5257": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5256": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5255": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5254": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5253": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5252": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5251": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5250": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5249": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5248": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5247": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5246": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5245": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5244": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5243": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5242": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5241": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5240": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5239": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5238": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5237": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5236": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5235": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5234": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5233": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5232": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5231": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5230": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5229": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5228": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5227": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5226": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5225": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5224": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5223": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5222": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5221": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5220": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5219": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5218": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5217": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5216": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5215": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5214": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5213": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5212": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5211": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5210": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5209": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5208": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5207": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5206": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5205": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5204": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5203": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5202": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5201": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5200": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5199": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5198": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5197": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5196": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5195": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5194": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5193": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5192": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5191": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5190": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5189": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5188": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5187": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5186": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5185": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5184": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5183": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5182": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5181": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5180": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5179": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5178": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5177": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5176": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5175": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5174": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5173": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5172": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5171": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5170": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5169": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5168": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5167": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5166": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5165": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5164": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5163": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5162": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5161": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5160": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5159": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5158": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5157": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5156": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5155": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5154": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5153": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5152": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5151": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5150": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5149": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5148": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5147": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5146": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5145": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5144": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5143": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5142": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5141": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5140": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5139": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5138": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5137": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5136": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5135": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5134": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5133": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5132": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5131": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5130": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5129": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5128": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5127": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5126": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5125": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5124": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5123": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5122": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5121": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5120": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5119": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5118": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5117": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5116": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5115": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5114": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5113": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5112": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5111": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5110": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5109": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5108": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5107": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5106": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5105": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5104": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5103": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5102": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5101": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5100": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5099": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5098": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5097": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5096": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5095": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5094": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5093": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5092": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5091": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5090": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5089": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5088": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5087": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5086": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5085": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5084": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5083": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5082": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5081": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5080": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5079": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5078": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5077": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5076": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5075": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5074": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5073": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5072": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5071": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5070": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5069": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5068": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5067": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5066": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5065": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5064": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5063": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5062": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5061": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5060": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5059": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5058": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5057": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5056": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5055": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5054": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5053": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5052": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5051": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5050": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5049": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5048": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5047": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5046": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5045": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5044": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5043": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5042": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5041": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5040": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5039": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5038": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5037": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5036": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5035": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5034": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5033": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5032": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5031": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5030": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5029": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5028": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5027": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5026": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5025": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5024": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5023": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5022": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5021": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5020": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5019": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5018": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5017": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5016": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5015": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5014": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5013": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5012": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5011": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5010": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5009": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5008": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5007": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5006": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5005": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5004": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5003": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5002": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5001": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5000": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4999": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4998": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4997": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4996": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4995": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4994": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4993": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4992": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4991": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4990": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4989": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4988": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4987": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4986": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4985": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4984": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4983": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4982": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4981": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4980": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4979": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4978": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4977": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4976": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4975": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4974": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4973": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4972": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4971": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4970": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4969": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4968": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4967": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4966": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4965": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4964": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4963": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4962": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4961": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4960": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4959": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4958": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4957": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4956": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4955": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4954": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4953": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4952": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4951": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4950": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4949": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4948": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4947": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4946": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4945": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4944": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4943": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4942": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4941": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4940": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4939": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4938": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4937": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4936": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4935": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4934": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4933": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4932": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4931": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4930": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4929": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4928": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4927": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4926": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4925": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4924": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4923": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4922": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4921": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4920": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4919": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4918": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4917": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4916": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4915": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4914": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4913": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4912": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4911": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4910": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4909": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4908": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4907": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4906": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4905": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4904": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4903": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4902": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4901": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4900": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4899": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4898": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4897": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4896": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4895": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4894": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4893": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4892": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4891": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4890": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4889": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4888": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4887": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4886": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4885": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4884": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4883": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4882": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4881": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4880": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4879": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4878": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4877": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4876": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4875": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4874": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4873": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4872": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4871": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4870": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4869": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4868": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4867": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4866": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4865": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4864": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4863": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4862": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4861": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4860": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4859": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4858": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4857": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4856": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4855": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4854": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4853": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4852": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4851": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4850": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4849": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4848": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4847": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4846": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4845": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4844": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4843": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4842": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4841": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4840": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4839": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4838": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4837": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4836": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4835": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4834": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4833": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4832": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4831": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4830": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4829": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4828": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4827": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4826": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4825": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4824": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4823": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4822": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4821": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4820": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4819": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4818": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4817": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4816": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4815": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4814": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4813": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4812": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4811": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4810": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4809": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4808": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4807": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4806": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4805": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4804": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4803": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4802": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4801": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4800": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4799": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4798": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4797": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4796": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4795": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4794": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4793": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4792": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4791": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4790": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4789": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4788": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4787": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4786": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4785": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4784": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4783": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4782": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4781": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4780": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4779": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4778": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4777": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4776": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4775": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4774": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4773": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4772": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4771": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4770": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4769": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4768": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4767": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4766": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4765": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4764": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4763": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4762": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4761": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4760": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4759": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4758": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4757": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4756": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4755": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4754": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4753": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4752": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4751": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4750": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4749": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4748": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4747": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4746": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4745": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4744": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4743": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4742": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4741": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4740": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4739": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4738": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4737": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4736": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4735": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4734": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4733": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4732": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4731": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4730": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4729": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4728": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4727": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4726": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4725": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4724": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4723": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4722": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4721": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4720": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4719": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4718": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4717": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4716": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4715": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4714": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4713": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4712": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4711": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4710": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4709": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4708": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4707": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4706": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4705": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4704": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4703": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4702": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4701": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4700": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4699": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4698": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4697": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4696": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4695": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4694": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4693": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4692": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4691": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4690": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4689": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4688": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4687": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4686": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4685": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4684": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4683": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4682": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4681": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4680": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4679": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4678": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4677": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4676": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4675": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4674": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4673": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4672": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4671": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4670": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4669": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4668": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4667": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4666": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4665": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4664": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4663": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4662": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4661": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4660": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4659": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4658": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4657": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4656": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4655": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4654": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4653": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4652": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4651": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4650": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4649": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4648": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4647": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4646": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4645": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4644": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4643": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4642": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4641": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4640": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4639": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4638": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4637": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4636": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4635": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4634": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4633": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4632": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4631": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4630": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4629": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4628": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4627": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4626": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4625": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4624": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4623": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4622": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4621": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4620": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4619": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4618": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4617": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4616": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4615": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4614": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4613": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4612": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4611": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4610": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4609": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4608": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4607": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4606": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4605": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4604": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4603": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4602": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4601": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4600": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4599": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4598": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4597": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4596": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4595": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4594": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4593": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4592": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4591": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4590": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4589": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4588": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4587": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4586": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4585": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4584": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4583": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4582": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4581": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4580": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4579": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4578": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4577": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4576": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4575": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4574": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4573": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4572": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4571": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4570": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4569": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4568": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4567": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4566": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4565": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4564": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4563": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4562": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4561": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4560": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4559": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4558": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4557": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4556": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4555": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4554": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4553": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4552": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4551": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4550": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4549": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4548": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4547": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4546": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4545": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4544": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4543": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4542": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4541": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4540": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4539": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4538": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4537": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4536": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4535": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4534": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4533": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4532": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4531": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4530": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4529": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4528": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4527": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4526": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4525": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4524": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4523": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4522": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4521": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4520": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4519": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4518": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4517": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4516": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4515": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4514": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4513": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4512": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4511": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4510": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4509": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4508": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4507": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4506": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4505": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4504": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4503": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4502": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4501": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4500": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4499": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4498": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4497": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4496": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4495": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4494": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4493": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4492": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4491": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4490": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4489": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4488": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4487": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4486": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4485": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4484": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4483": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4482": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4481": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4480": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4479": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4478": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4477": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4476": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4475": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4474": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4473": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4472": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4471": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4470": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4469": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4468": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4467": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4466": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4465": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4464": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4463": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4462": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4461": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4460": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4459": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4458": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4457": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4456": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4455": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4454": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4453": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4452": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4451": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4450": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4449": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4448": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4447": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4446": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4445": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4444": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4443": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4442": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4441": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4440": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4439": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4438": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4437": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4436": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4435": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4434": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4433": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4432": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4431": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4430": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4429": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4428": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4427": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4426": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4425": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4424": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4423": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4422": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4421": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4420": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4419": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4418": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4417": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4416": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4415": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4414": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4413": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4412": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4411": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4410": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4409": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4408": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4407": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4406": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4405": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4404": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4403": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4402": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4401": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4400": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4399": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4398": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4397": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4396": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4395": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4394": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4393": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4392": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4391": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4390": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4389": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4388": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4387": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4386": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4385": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4384": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4383": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4382": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4381": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4380": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4379": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4378": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4377": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4376": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4375": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4374": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4373": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4372": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4371": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4370": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4369": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4368": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4367": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4366": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4365": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4364": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4363": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4362": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4361": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4360": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4359": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4358": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4357": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4356": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4355": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4354": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4353": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4352": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4351": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4350": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4349": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4348": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4347": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4346": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4345": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4344": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4343": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4342": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4341": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4340": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4339": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4338": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4337": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4336": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4335": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4334": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4333": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4332": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4331": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4330": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4329": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4328": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4327": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4326": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4325": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4324": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4323": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4322": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4321": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4320": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4319": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4318": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4317": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4316": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4315": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4314": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4313": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4312": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4311": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4310": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4309": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4308": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4307": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4306": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4305": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4304": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4303": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4302": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4301": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4300": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4299": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4298": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4297": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4296": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4295": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4294": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4293": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4292": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4291": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4290": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4289": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4288": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4287": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4286": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4285": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4284": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4283": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4282": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4281": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4280": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4279": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4278": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4277": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4276": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4275": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4274": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4273": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4272": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4271": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4270": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4269": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4268": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4267": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4266": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4265": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4264": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4263": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4262": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4261": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4260": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4259": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4258": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4257": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4256": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4255": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4254": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4253": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4252": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4251": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4250": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4249": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4248": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4247": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4246": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4245": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4244": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4243": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4242": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4241": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4240": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4239": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4238": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4237": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4236": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4235": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4234": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4233": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4232": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4231": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4230": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4229": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4228": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4227": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4226": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4225": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4224": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4223": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4222": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4221": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4220": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4219": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4218": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4217": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4216": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4215": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4214": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4213": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4212": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4211": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4210": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4209": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4208": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4207": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4206": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4205": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4204": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4203": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4202": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4201": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4200": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4199": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4198": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4197": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4196": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4195": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4194": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4193": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4192": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4191": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4190": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4189": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4188": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4187": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4186": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4185": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4184": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4183": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4182": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4181": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4180": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4179": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4178": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4177": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4176": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4175": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4174": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4173": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4172": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4171": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4170": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4169": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4168": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4167": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4166": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4165": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4164": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4163": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4162": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4161": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4160": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4159": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4158": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4157": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4156": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4155": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4154": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4153": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4152": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4151": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4150": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4149": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4148": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4147": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4146": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4145": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4144": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4143": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4142": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4141": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4140": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4139": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4138": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4137": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4136": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4135": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4134": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4133": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4132": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4131": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4130": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4129": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4128": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4127": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4126": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4125": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4124": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4123": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4122": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4121": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4120": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4119": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4118": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4117": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4116": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4115": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4114": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4113": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4112": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4111": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4110": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4109": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4108": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4107": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4106": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4105": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4104": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4103": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4102": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4101": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4100": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4099": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4098": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4097": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4096": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4095": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4094": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4093": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4092": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4091": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4090": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4089": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4088": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4087": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4086": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4085": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4084": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4083": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4082": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4081": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4080": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4079": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4078": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4077": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4076": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4075": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4074": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4073": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4072": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4071": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4070": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4069": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4068": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4067": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4066": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4065": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4064": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4063": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4062": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4061": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4060": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4059": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4058": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4057": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4056": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4055": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4054": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4053": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4052": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4051": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4050": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4049": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4048": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4047": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4046": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4045": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4044": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4043": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4042": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4041": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4040": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4039": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4038": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4037": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4036": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4035": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4034": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4033": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4032": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4031": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4030": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4029": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4028": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4027": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4026": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4025": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4024": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4023": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4022": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4021": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4020": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4019": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4018": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4017": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4016": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4015": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4014": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4013": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4012": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4011": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4010": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4009": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4008": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4007": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4006": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4005": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4004": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4003": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4002": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4001": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4000": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3999": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3998": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3997": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3996": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3995": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3994": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3993": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3992": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3991": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3990": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3989": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3988": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3987": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3986": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3985": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3984": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3983": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3982": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3981": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3980": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3979": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3978": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3977": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3976": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3975": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3974": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3973": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3972": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3971": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3970": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3969": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3968": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3967": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3966": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3965": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3964": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3963": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3962": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3961": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3960": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3959": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3958": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3957": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3956": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3955": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3954": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3953": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3952": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3951": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3950": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3949": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3948": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3947": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3946": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3945": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3944": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3943": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3942": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3941": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3940": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3939": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3938": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3937": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3936": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3935": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3934": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3933": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3932": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3931": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3930": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3929": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3928": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3927": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3926": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3925": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3924": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3923": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3922": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3921": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3920": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3919": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3918": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3917": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3916": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3915": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3914": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3913": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3912": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3911": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3910": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3909": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3908": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3907": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3906": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3905": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3904": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3903": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3902": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3901": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3900": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3899": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3898": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3897": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3896": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3895": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3894": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3893": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3892": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3891": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3890": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3889": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3888": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3887": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3886": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3885": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3884": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3883": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3882": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3881": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3880": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3879": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3878": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3877": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3876": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3875": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3874": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3873": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3872": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3871": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3870": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3869": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3868": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3867": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3866": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3865": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3864": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3863": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3862": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3861": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3860": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3859": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3858": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3857": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3856": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3855": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3854": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3853": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3852": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3851": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3850": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3849": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3848": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3847": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3846": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3845": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3844": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3843": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3842": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3841": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3840": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3839": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3838": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3837": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3836": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3835": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3834": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3833": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3832": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3831": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3830": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3829": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3828": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3827": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3826": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3825": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3824": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3823": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3822": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3821": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3820": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3819": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3818": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3817": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3816": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3815": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3814": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3813": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3812": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3811": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3810": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3809": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3808": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3807": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3806": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3805": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3804": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3803": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3802": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3801": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3800": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3799": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3798": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3797": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3796": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3795": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3794": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3793": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3792": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3791": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3790": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3789": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3788": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3787": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3786": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3785": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3784": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3783": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3782": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3781": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3780": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3779": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3778": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3777": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3776": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3775": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3774": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3773": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3772": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3771": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3770": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3769": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3768": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3767": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3766": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3765": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3764": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3763": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3762": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3761": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3760": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3759": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3758": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3757": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3756": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3755": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3754": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3753": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3752": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3751": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3750": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3749": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3748": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3747": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3746": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3745": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3744": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3743": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3742": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3741": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3740": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3739": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3738": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3737": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3736": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3735": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3734": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3733": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3732": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3731": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3730": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3729": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3728": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3727": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3726": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3725": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3724": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3723": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3722": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3721": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3720": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3719": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3718": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3717": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3716": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3715": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3714": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3713": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3712": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3711": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3710": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3709": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3708": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3707": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3706": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3705": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3704": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3703": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3702": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3701": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3700": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3699": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3698": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3697": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3696": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3695": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3694": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3693": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3692": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3691": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3690": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3689": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3688": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3687": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3686": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3685": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3684": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3683": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3682": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3681": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3680": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3679": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3678": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3677": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3676": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3675": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3674": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3673": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3672": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3671": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3670": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3669": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3668": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3667": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3666": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3665": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3664": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3663": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3662": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3661": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3660": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3659": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3658": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3657": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3656": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3655": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3654": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3653": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3652": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3651": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3650": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3649": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3648": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3647": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3646": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3645": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3644": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3643": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3642": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3641": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3640": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3639": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3638": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3637": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3636": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3635": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3634": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3633": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3632": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3631": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3630": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3629": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3628": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3627": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3626": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3625": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3624": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3623": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3622": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3621": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3620": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3619": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3618": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3617": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3616": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3615": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3614": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3613": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3612": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3611": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3610": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3609": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3608": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3607": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3606": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3605": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3604": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3603": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3602": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3601": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3600": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3599": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3598": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3597": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3596": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3595": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3594": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3593": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3592": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3591": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3590": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3589": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3588": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3587": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3586": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3585": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3584": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3583": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3582": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3581": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3580": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3579": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3578": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3577": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3576": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3575": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3574": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3573": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3572": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3571": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3570": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3569": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3568": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3567": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3566": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3565": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3564": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3563": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3562": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3561": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3560": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3559": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3558": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3557": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3556": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3555": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3554": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3553": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3552": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3551": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3550": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3549": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3548": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3547": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3546": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3545": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3544": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3543": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3542": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3541": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3540": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3539": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3538": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3537": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3536": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3535": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3534": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3533": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3532": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3531": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3530": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3529": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3528": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3527": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3526": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3525": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3524": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3523": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3522": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3521": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3520": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3519": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3518": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3517": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3516": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3515": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3514": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3513": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3512": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3511": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3510": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3509": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3508": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3507": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3506": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3505": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3504": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3503": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3502": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3501": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3500": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3499": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3498": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3497": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3496": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3495": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3494": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3493": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3492": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3491": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3490": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3489": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3488": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3487": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3486": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3485": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3484": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3483": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3482": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3481": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3480": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3479": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3478": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3477": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3476": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3475": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3474": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3473": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3472": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3471": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3470": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3469": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3468": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3467": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3466": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3465": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3464": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3463": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3462": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3461": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3460": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3459": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3458": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3457": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3456": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3455": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3454": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3453": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3452": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3451": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3450": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3449": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3448": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3447": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3446": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3445": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3444": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3443": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3442": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3441": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3440": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3439": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3438": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3437": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3436": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3435": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3434": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3433": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3432": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3431": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3430": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3429": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3428": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3427": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3426": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3425": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3424": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3423": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3422": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3421": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3420": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3419": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3418": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3417": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3416": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3415": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3414": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3413": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3412": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3411": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3410": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3409": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3408": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3407": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3406": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3405": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3404": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3403": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3402": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3401": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3400": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3399": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3398": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3397": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3396": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3395": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3394": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3393": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3392": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3391": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3390": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3389": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3388": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3387": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3386": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3385": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3384": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3383": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3382": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3381": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3380": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3379": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3378": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3377": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3376": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3375": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3374": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3373": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3372": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3371": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3370": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3369": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3368": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3367": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3366": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3365": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3364": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3363": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3362": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3361": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3360": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3359": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3358": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3357": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3356": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3355": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3354": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3353": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3352": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3351": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3350": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3349": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3348": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3347": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3346": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3345": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3344": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3343": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3342": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3341": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3340": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3339": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3338": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3337": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3336": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3335": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3334": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3333": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3332": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3331": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3330": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3329": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3328": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3327": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3326": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3325": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3324": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3323": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3322": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3321": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3320": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3319": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3318": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3317": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3316": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3315": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3314": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3313": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3312": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3311": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3310": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3309": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3308": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3307": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3306": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3305": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3304": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3303": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3302": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3301": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3300": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3299": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3298": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3297": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3296": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3295": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3294": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3293": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3292": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3291": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3290": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3289": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3288": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3287": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3286": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3285": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3284": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3283": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3282": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3281": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3280": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3279": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3278": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3277": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3276": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3275": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3274": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3273": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3272": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3271": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3270": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3269": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3268": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3267": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3266": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3265": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3264": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3263": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3262": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3261": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3260": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3259": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3258": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3257": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3256": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3255": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3254": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3253": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3252": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3251": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3250": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3249": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3248": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3247": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3246": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3245": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3244": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3243": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3242": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3241": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3240": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3239": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3238": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3237": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3236": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3235": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3234": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3233": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3232": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3231": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3230": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3229": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3228": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3227": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3226": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3225": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3224": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3223": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3222": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3221": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3220": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3219": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3218": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3217": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3216": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3215": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3214": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3213": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3212": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3211": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3210": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3209": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3208": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3207": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3206": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3205": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3204": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3203": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3202": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3201": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3200": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3199": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3198": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3197": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3196": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3195": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3194": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3193": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3192": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3191": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3190": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3189": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3188": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3187": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3186": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3185": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3184": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3183": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3182": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3181": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3180": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3179": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3178": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3177": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3176": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3175": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3174": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3173": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3172": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3171": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3170": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3169": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3168": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3167": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3166": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3165": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3164": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3163": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3162": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3161": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3160": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3159": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3158": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3157": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3156": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3155": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3154": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3153": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3152": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3151": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3150": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3149": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3148": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3147": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3146": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3145": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3144": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3143": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3142": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3141": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3140": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3139": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3138": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3137": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3136": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3135": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3134": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3133": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3132": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3131": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3130": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3129": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3128": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3127": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3126": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3125": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3124": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3123": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3122": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3121": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3120": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3119": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3118": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3117": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3116": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3115": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3114": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3113": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3112": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3111": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3110": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3109": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3108": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3107": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3106": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3105": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3104": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3103": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3102": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3101": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3100": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3099": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3098": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3097": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3096": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3095": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3094": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3093": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3092": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3091": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3090": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3089": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3088": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3087": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3086": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3085": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3084": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3083": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3082": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3081": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3080": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3079": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3078": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3077": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3076": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3075": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3074": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3073": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3072": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3071": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3070": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3069": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3068": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3067": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3066": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3065": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3064": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3063": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3062": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3061": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3060": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3059": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3058": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3057": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3056": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3055": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3054": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3053": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3052": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3051": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3050": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3049": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3048": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3047": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3046": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3045": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3044": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3043": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3042": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3041": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3040": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3039": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3038": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3037": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3036": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3035": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3034": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3033": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3032": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3031": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3030": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3029": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3028": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3027": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3026": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3025": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3024": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3023": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3022": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3021": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3020": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3019": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3018": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3017": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3016": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3015": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3014": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3013": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3012": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3011": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3010": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3009": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3008": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3007": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3006": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3005": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3004": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3003": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3002": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3001": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3000": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2999": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2998": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2997": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2996": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2995": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2994": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2993": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2992": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2991": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2990": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2989": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2988": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2987": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2986": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2985": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2984": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2983": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2982": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2981": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2980": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2979": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2978": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2977": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2976": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2975": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2974": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2973": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2972": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2971": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2970": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2969": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2968": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2967": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2966": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2965": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2964": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2963": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2962": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2961": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2960": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2959": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2958": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2957": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2956": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2955": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2954": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2953": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2952": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2951": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2950": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2949": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2948": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2947": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2946": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2945": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2944": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2943": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2942": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2941": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2940": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2939": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2938": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2937": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2936": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2935": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2934": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2933": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2932": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2931": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2930": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2929": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2928": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2927": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2926": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2925": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2924": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2923": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2922": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2921": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2920": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2919": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2918": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2917": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2916": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2915": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2914": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2913": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2912": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2911": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2910": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2909": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2908": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2907": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2906": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2905": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2904": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2903": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2902": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2901": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2900": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2899": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2898": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2897": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2896": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2895": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2894": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2893": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2892": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2891": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2890": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2889": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2888": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2887": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2886": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2885": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2884": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2883": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2882": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2881": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2880": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2879": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2878": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2877": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2876": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2875": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2874": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2873": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2872": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2871": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2870": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2869": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2868": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2867": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2866": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2865": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2864": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2863": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2862": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2861": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2860": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2859": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2858": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2857": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2856": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2855": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2854": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2853": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2852": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2851": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2850": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2849": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2848": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2847": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2846": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2845": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2844": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2843": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2842": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2841": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2840": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2839": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2838": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2837": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2836": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2835": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2834": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2833": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2832": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2831": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2830": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2829": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2828": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2827": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2826": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2825": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2824": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2823": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2822": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2821": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2820": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2819": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2818": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2817": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2816": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2815": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2814": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2813": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2812": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2811": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2810": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2809": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2808": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2807": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2806": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2805": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2804": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2803": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2802": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2801": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2800": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2799": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2798": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2797": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2796": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2795": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2794": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2793": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2792": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2791": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2790": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2789": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2788": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2787": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2786": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2785": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2784": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2783": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2782": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2781": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2780": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2779": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2778": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2777": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2776": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2775": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2774": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2773": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2772": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2771": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2770": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2769": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2768": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2767": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2766": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2765": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2764": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2763": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2762": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2761": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2760": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2759": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2758": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2757": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2756": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2755": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2754": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2753": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2752": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2751": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2750": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2749": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2748": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2747": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2746": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2745": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2744": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2743": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2742": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2741": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2740": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2739": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2738": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2737": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2736": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2735": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2734": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2733": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2732": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2731": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2730": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2729": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2728": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2727": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2726": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2725": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2724": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2723": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2722": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2721": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2720": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2719": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2718": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2717": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2716": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2715": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2714": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2713": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2712": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2711": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2710": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2709": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2708": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2707": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2706": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2705": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2704": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2703": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2702": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2701": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2700": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2699": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2698": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2697": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2696": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2695": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2694": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2693": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2692": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2691": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2690": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2689": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2688": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2687": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2686": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2685": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2684": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2683": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2682": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2681": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2680": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2679": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2678": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2677": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2676": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2675": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2674": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2673": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2672": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2671": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2670": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2669": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2668": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2667": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2666": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2665": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2664": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2663": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2662": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2661": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2660": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2659": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2658": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2657": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2656": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2655": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2654": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2653": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2652": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2651": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2650": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2649": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2648": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2647": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2646": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2645": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2644": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2643": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2642": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2641": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2640": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2639": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2638": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2637": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2636": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2635": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2634": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2633": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2632": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2631": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2630": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2629": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2628": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2627": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2626": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2625": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2624": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2623": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2622": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2621": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2620": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2619": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2618": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2617": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2616": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2615": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2614": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2613": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2612": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2611": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2610": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2609": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2608": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2607": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2606": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2605": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2604": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2603": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2602": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2601": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2600": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2599": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2598": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2597": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2596": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2595": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2594": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2593": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2592": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2591": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2590": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2589": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2588": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2587": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2586": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2585": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2584": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2583": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2582": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2581": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2580": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2579": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2578": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2577": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2576": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2575": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2574": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2573": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2572": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2571": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2570": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2569": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2568": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2567": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2566": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2565": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2564": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2563": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2562": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2561": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2560": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2559": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2558": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2557": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2556": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2555": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2554": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2553": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2552": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2551": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2550": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2549": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2548": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2547": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2546": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2545": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2544": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2543": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2542": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2541": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2540": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2539": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2538": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2537": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2536": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2535": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2534": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2533": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2532": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2531": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2530": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2529": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2528": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2527": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2526": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2525": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2524": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2523": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2522": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2521": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2520": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2519": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2518": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2517": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2516": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2515": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2514": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2513": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2512": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2511": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2510": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2509": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2508": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2507": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2506": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2505": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2504": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2503": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2502": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2501": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2500": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2499": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2498": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2497": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2496": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2495": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2494": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2493": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2492": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2491": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2490": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2489": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2488": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2487": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2486": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2485": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2484": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2483": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2482": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2481": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2480": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2479": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2478": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2477": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2476": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2475": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2474": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2473": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2472": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2471": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2470": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2469": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2468": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2467": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2466": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2465": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2464": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2463": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2462": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2461": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2460": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2459": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2458": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2457": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2456": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2455": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2454": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2453": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2452": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2451": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2450": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2449": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2448": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2447": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2446": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2445": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2444": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2443": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2442": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2441": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2440": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2439": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2438": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2437": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2436": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2435": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2434": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2433": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2432": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2431": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2430": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2429": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2428": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2427": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2426": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2425": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2424": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2423": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2422": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2421": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2420": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2419": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2418": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2417": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2416": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2415": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2414": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2413": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2412": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2411": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2410": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2409": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2408": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2407": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2406": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2405": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2404": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2403": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2402": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2401": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2400": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2399": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2398": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2397": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2396": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2395": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2394": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2393": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2392": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2391": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2390": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2389": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2388": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2387": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2386": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2385": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2384": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2383": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2382": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2381": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2380": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2379": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2378": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2377": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2376": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2375": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2374": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2373": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2372": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2371": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2370": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2369": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2368": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2367": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2366": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2365": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2364": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2363": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2362": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2361": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2360": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2359": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2358": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2357": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2356": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2355": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2354": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2353": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2352": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2351": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2350": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2349": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2348": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2347": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2346": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2345": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2344": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2343": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2342": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2341": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2340": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2339": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2338": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2337": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2336": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2335": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2334": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2333": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2332": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2331": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2330": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2329": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2328": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2327": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2326": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2325": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2324": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2323": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2322": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2321": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2320": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2319": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2318": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2317": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2316": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2315": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2314": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2313": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2312": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2311": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2310": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2309": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2308": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2307": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2306": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2305": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2304": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2303": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2302": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2301": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2300": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2299": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2298": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2297": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2296": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2295": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2294": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2293": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2292": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2291": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2290": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2289": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2288": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2287": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2286": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2285": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2284": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2283": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2282": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2281": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2280": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2279": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2278": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2277": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2276": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2275": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2274": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2273": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2272": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2271": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2270": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2269": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2268": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2267": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2266": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2265": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2264": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2263": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2262": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2261": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2260": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2259": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2258": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2257": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2256": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2255": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2254": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2253": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2252": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2251": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2250": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2249": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2248": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2247": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2246": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2245": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2244": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2243": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2242": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2241": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2240": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2239": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2238": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2237": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2236": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2235": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2234": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2233": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2232": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2231": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2230": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2229": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2228": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2227": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2226": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2225": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2224": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2223": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2222": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2221": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2220": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2219": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2218": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2217": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2216": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2215": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2214": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2213": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2212": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2211": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2210": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2209": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2208": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2207": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2206": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2205": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2204": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2203": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2202": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2201": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2200": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2199": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2198": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2197": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2196": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2195": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2194": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2193": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2192": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2191": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2190": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2189": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2188": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2187": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2186": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2185": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2184": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2183": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2182": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2181": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2180": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2179": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2178": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2177": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2176": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2175": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2174": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2173": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2172": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2171": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2170": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2169": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2168": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2167": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2166": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2165": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2164": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2163": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2162": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2161": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2160": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2159": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2158": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2157": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2156": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2155": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2154": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2153": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2152": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2151": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2150": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2149": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2148": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2147": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2146": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2145": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2144": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2143": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2142": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2141": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2140": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2139": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2138": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2137": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2136": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2135": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2134": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2133": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2132": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2131": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2130": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2129": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2128": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2127": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2126": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2125": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2124": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2123": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2122": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2121": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2120": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2119": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2118": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2117": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2116": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2115": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2114": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2113": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2112": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2111": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2110": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2109": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2108": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2107": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2106": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2105": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2104": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2103": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2102": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2101": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2100": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2099": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2098": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2097": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2096": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2095": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2094": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2093": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2092": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2091": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2090": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2089": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2088": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2087": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2086": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2085": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2084": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2083": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2082": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2081": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2080": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2079": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2078": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2077": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2076": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2075": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2074": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2073": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2072": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2071": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2070": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2069": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2068": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2067": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2066": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2065": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2064": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2063": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2062": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2061": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2060": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2059": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2058": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2057": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2056": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2055": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2054": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2053": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2052": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2051": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2050": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2049": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2048": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2047": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2046": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2045": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2044": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2043": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2042": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2041": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2040": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2039": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2038": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2037": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2036": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2035": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2034": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2033": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2032": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2031": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2030": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2029": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2028": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2027": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2026": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2025": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2024": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2023": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2022": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2021": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2020": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2019": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2018": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2017": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2016": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2015": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2014": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2013": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2012": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2011": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2010": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2009": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2008": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2007": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2006": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2005": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2004": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2003": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2002": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2001": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2000": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1999": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1998": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1997": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1996": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1995": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1994": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1993": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1992": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1991": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1990": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1989": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1988": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1987": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1986": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1985": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1984": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1983": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1982": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1981": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1980": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1979": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1978": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1977": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1976": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1975": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1974": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1973": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1972": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1971": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1970": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1969": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1968": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1967": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1966": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1965": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1964": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1963": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1962": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1961": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1960": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1959": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1958": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1957": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1956": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1955": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1954": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1953": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1952": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1951": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1950": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1949": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1948": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1947": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1946": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1945": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1944": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1943": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1942": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1941": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1940": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1939": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1938": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1937": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1936": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1935": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1934": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1933": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1932": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1931": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1930": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1929": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1928": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1927": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1926": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1925": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1924": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1923": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1922": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1921": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1920": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1919": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1918": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1917": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1916": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1915": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1914": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1913": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1912": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1911": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1910": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1909": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1908": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1907": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1906": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1905": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1904": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1903": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1902": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1901": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1900": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1899": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1898": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1897": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1896": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1895": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1894": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1893": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1892": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1891": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1890": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1889": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1888": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1887": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1886": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1885": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1884": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1883": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1882": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1881": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1880": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1879": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1878": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1877": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1876": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1875": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1874": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1873": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1872": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1871": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1870": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1869": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1868": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1867": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1866": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1865": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1864": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1863": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1862": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1861": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1860": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1859": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1858": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1857": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1856": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1855": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1854": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1853": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1852": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1851": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1850": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1849": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1848": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1847": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1846": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1845": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1844": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1843": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1842": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1841": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1840": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1839": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1838": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1837": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1836": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1835": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1834": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1833": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1832": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1831": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1830": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1829": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1828": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1827": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1826": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1825": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1824": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1823": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1822": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1821": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1820": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1819": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1818": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1817": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1816": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1815": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1814": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1813": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1812": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1811": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1810": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1809": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1808": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1807": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1806": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1805": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1804": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1803": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1802": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1801": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1800": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1799": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1798": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1797": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1796": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1795": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1794": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1793": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1792": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1791": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1790": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1789": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1788": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1787": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1786": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1785": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1784": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1783": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1782": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1781": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1780": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1779": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1778": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1777": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1776": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1775": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1774": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1773": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1772": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1771": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1770": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1769": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1768": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1767": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1766": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1765": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1764": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1763": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1762": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1761": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1760": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1759": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1758": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1757": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1756": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1755": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1754": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1753": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1752": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1751": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1750": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1749": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1748": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1747": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1746": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1745": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1744": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1743": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1742": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1741": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1740": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1739": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1738": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1737": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1736": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1735": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1734": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1733": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1732": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1731": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1730": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1729": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1728": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1727": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1726": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1725": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1724": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1723": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1722": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1721": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1720": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1719": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1718": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1717": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1716": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1715": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1714": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1713": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1712": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1711": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1710": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1709": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1708": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1707": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1706": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1705": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1704": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1703": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1702": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1701": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1700": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1699": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1698": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1697": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1696": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1695": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1694": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1693": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1692": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1691": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1690": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1689": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1688": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1687": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1686": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1685": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1684": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1683": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1682": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1681": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1680": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1679": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1678": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1677": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1676": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1675": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1674": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1673": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1672": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1671": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1670": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1669": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1668": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1667": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1666": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1665": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1664": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1663": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1662": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1661": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1660": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1659": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1658": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1657": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1656": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1655": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1654": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1653": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1652": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1651": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1650": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1649": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1648": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1647": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1646": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1645": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1644": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1643": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1642": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1641": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1640": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1639": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1638": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1637": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1636": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1635": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1634": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1633": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1632": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1631": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1630": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1629": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1628": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1627": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1626": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1625": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1624": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1623": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1622": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1621": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1620": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1619": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1618": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1617": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1616": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1615": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1614": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1613": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1612": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1611": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1610": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1609": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1608": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1607": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1606": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1605": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1604": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1603": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1602": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1601": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1600": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1599": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1598": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1597": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1596": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1595": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1594": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1593": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1592": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1591": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1590": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1589": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1588": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1587": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1586": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1585": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1584": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1583": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1582": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1581": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1580": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1579": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1578": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1577": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1576": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1575": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1574": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1573": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1572": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1571": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1570": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1569": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1568": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1567": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1566": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1565": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1564": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1563": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1562": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1561": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1560": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1559": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1558": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1557": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1556": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1555": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1554": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1553": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1552": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1551": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1550": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1549": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1548": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1547": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1546": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1545": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1544": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1543": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1542": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1541": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1540": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1539": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1538": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1537": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1536": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1535": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1534": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1533": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1532": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1531": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1530": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1529": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1528": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1527": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1526": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1525": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1524": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1523": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1522": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1521": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1520": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1519": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1518": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1517": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1516": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1515": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1514": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1513": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1512": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1511": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1510": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1509": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1508": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1507": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1506": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1505": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1504": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1503": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1502": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1501": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1500": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1499": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1498": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1497": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1496": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1495": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1494": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1493": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1492": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1491": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1490": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1489": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1488": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1487": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1486": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1485": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1484": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1483": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1482": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1481": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1480": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1479": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1478": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1477": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1476": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1475": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1474": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1473": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1472": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1471": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1470": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1469": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1468": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1467": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1466": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1465": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1464": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1463": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1462": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1461": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1460": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1459": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1458": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1457": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1456": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1455": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1454": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1453": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1452": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1451": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1450": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1449": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1448": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1447": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1446": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1445": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1444": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1443": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1442": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1441": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1440": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1439": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1438": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1437": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1436": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1435": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1434": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1433": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1432": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1431": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1430": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1429": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1428": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1427": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1426": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1425": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1424": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1423": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1422": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1421": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1420": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1419": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1418": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1417": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1416": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1415": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1414": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1413": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1412": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1411": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1410": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1409": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1408": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1407": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1406": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1405": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1404": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1403": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1402": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1401": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1400": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1399": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1398": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1397": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1396": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1395": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1394": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1393": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1392": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1391": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1390": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1389": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1388": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1387": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1386": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1385": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1384": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1383": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1382": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1381": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1380": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1379": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1378": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1377": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1376": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1375": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1374": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1373": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1372": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1371": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1370": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1369": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1368": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1367": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1366": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1365": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1364": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1363": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1362": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1361": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1360": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1359": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1358": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1357": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1356": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1355": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1354": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1353": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1352": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1351": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1350": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1349": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1348": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1347": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1346": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1345": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1344": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1343": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1342": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1341": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1340": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1339": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1338": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1337": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1336": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1335": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1334": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1333": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1332": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1331": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1330": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1329": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1328": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1327": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1326": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1325": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1324": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1323": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1322": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1321": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1320": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1319": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1318": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1317": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1316": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1315": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1314": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1313": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1312": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1311": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1310": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1309": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1308": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1307": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1306": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1305": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1304": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1303": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1302": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1301": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1300": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1299": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1298": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1297": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1296": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1295": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1294": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1293": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1292": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1291": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1290": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1289": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1288": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1287": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1286": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1285": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1284": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1283": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1282": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1281": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1280": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1279": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1278": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1277": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1276": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1275": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1274": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1273": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1272": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1271": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1270": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1269": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1268": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1267": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1266": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1265": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1264": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1263": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1262": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1261": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1260": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1259": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1258": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1257": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1256": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1255": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1254": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1253": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1252": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1251": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1250": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1249": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1248": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1247": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1246": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1245": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1244": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1243": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1242": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1241": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1240": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1239": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1238": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1237": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1236": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1235": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1234": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1233": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1232": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1231": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1230": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1229": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1228": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1227": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1226": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1225": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1224": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1223": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1222": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1221": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1220": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1219": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1218": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1217": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1216": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1215": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1214": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1213": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1212": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1211": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1210": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1209": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1208": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1207": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1206": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1205": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1204": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1203": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1202": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1201": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1200": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1199": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1198": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1197": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1196": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1195": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1194": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1193": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1192": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1191": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1190": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1189": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1188": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1187": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1186": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1185": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1184": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1183": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1182": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1181": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1180": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1179": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1178": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1177": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1176": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1175": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1174": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1173": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1172": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1171": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1170": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1169": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1168": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1167": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1166": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1165": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1164": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1163": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1162": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1161": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1160": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1159": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1158": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1157": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1156": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1155": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1154": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1153": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1152": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1151": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1150": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1149": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1148": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1147": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1146": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1145": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1144": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1143": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1142": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1141": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1140": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1139": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1138": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1137": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1136": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1135": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1134": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1133": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1132": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1131": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1130": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1129": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1128": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1127": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1126": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1125": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1124": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1123": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1122": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1121": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1120": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1119": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1118": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1117": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1116": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1115": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1114": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1113": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1112": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1111": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1110": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1109": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1108": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1107": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1106": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1105": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1104": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1103": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1102": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1101": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1100": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1099": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1098": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1097": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1096": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1095": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1094": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1093": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1092": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1091": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1090": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1089": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1088": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1087": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1086": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1085": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1084": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1083": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1082": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1081": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1080": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1079": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1078": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1077": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1076": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1075": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1074": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1073": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1072": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1071": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1070": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1069": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1068": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1067": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1066": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1065": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1064": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1063": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1062": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1061": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1060": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1059": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1058": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1057": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1056": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1055": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1054": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1053": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1052": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1051": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1050": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1049": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1048": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1047": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1046": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1045": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1044": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1043": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1042": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1041": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1040": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1039": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1038": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1037": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1036": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1035": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1034": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1033": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1032": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1031": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1030": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1029": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1028": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1027": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1026": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1025": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1024": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1023": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1022": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1021": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1020": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1019": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1018": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1017": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1016": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1015": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1014": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1013": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1012": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1011": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1010": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1009": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1008": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1007": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1006": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1005": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1004": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1003": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1002": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1001": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1000": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-999": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-998": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-997": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-996": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-995": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-994": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-993": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-992": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-991": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-990": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-989": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-988": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-987": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-986": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-985": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-984": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-983": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-982": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-981": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-980": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-979": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-978": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-977": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-976": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-975": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-974": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-973": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-972": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-971": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-970": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-969": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-968": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-967": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-966": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-965": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-964": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-963": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-962": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-961": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-960": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-959": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-958": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-957": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-956": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-955": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-954": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-953": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-952": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-951": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-950": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-949": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-948": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-947": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-946": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-945": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-944": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-943": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-942": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-941": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-940": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-939": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-938": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-937": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-936": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-935": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-934": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-933": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-932": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-931": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-930": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-929": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-928": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-927": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-926": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-925": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-924": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-923": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-922": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-921": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-920": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-919": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-918": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-917": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-916": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-915": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-914": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-913": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-912": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-911": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-910": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-909": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-908": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-907": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-906": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-905": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-904": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-903": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-902": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-901": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-900": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-899": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-898": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-897": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-896": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-895": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-894": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-893": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-892": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-891": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-890": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-889": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-888": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-887": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-886": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-885": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-884": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-883": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-882": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-881": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-880": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-879": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-878": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-877": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-876": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-875": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-874": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-873": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-872": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-871": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-870": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-869": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-868": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-867": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-866": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-865": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-864": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-863": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-862": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-861": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-860": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-859": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-858": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-857": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-856": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-855": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-854": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-853": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-852": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-851": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-850": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-849": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-848": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-847": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-846": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-845": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-844": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-843": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-842": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-841": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-840": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-839": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-838": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-837": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-836": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-835": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-834": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-833": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-832": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-831": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-830": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-829": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-828": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-827": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-826": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-825": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-824": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-823": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-822": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-821": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-820": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-819": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-818": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-817": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-816": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-815": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-814": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-813": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-812": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-811": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-810": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-809": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-808": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-807": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-806": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-805": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-804": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-803": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-802": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-801": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-800": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-799": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-798": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-797": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-796": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-795": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-794": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-793": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-792": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-791": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-790": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-789": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-788": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-787": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-786": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-785": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-784": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-783": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-782": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-781": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-780": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-779": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-778": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-777": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-776": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-775": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-774": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-773": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-772": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-771": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-770": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-769": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-768": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-767": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-766": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-765": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-764": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-763": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-762": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-761": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-760": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-759": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-758": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-757": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-756": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-755": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-754": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-753": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-752": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-751": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-750": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-749": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-748": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-747": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-746": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-745": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-744": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-743": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-742": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-741": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-740": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-739": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-738": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-737": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-736": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-735": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-734": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-733": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-732": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-731": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-730": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-729": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-728": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-727": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-726": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-725": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-724": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-723": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-722": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-721": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-720": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-719": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-718": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-717": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-716": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-715": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-714": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-713": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-712": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-711": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-710": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-709": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-708": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-707": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-706": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-705": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-704": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-703": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-702": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-701": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-700": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-699": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-698": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-697": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-696": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-695": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-694": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-693": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-692": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-691": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-690": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-689": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-688": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-687": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-686": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-685": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-684": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-683": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-682": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-681": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-680": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-679": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-678": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-677": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-676": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-675": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-674": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-673": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-672": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-671": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-670": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-669": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-668": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-667": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-666": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-665": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-664": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-663": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-662": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-661": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-660": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-659": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-658": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-657": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-656": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-655": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-654": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-653": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-652": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-651": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-650": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-649": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-648": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-647": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-646": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-645": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-644": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-643": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-642": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-641": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-640": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-639": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-638": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-637": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-636": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-635": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-634": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-633": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-632": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-631": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-630": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-629": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-628": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-627": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-626": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-625": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-624": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-623": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-622": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-621": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-620": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-619": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-618": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-617": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-616": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-615": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-614": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-613": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-612": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-611": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-610": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-609": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-608": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-607": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-606": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-605": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-604": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-603": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-602": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-601": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-600": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-599": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-598": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-597": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-596": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-595": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-594": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-593": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-592": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-591": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-590": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-589": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-588": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-587": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-586": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-585": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-584": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-583": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-582": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-581": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-580": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-579": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-578": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-577": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-576": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-575": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-574": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-573": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-572": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-571": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-570": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-569": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-568": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-567": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-566": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-565": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-564": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-563": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-562": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-561": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-560": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-559": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-558": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-557": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-556": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-555": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-554": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-553": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-552": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-551": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-550": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-549": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-548": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-547": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-546": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-545": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-544": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-543": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-542": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-541": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-540": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-539": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-538": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-537": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-536": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-535": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-534": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-533": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-532": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-531": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-530": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-529": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-528": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-527": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-526": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-525": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-524": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-523": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-522": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-521": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-520": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-519": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-518": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-517": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-516": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-515": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-514": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-513": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-512": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-511": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-510": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-509": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-508": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-507": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-506": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-505": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-504": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-503": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-502": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-501": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-500": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-499": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-498": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-497": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-496": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-495": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-494": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-493": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-492": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-491": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-490": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-489": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-488": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-487": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-486": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-485": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-484": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-483": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-482": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-481": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-480": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-479": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-478": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-477": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-476": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-475": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-474": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-473": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-472": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-471": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-470": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-469": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-468": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-467": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-466": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-465": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-464": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-463": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-462": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-461": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-460": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-459": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-458": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-457": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-456": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-455": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-454": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-453": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-452": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-451": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-450": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-449": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-448": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-447": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-446": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-445": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-444": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-443": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-442": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-441": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-440": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-439": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-438": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-437": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-436": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-435": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-434": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-433": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-432": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-431": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-430": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-429": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-428": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-427": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-426": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-425": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-424": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-423": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-422": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-421": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-420": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-419": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-418": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-417": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-416": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-415": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-414": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-413": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-412": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-411": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-410": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-409": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-408": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-407": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-406": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-405": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-404": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-403": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-402": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-401": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-400": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-399": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-398": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-397": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-396": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-395": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-394": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-393": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-392": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-391": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-390": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-389": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-388": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-387": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-386": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-385": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-384": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-383": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-382": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-381": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-380": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-379": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-378": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-377": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-376": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-375": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-374": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-373": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-372": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-371": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-370": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-369": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-368": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-367": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-366": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-365": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-364": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-363": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-362": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-361": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-360": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-359": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-358": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-357": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-356": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-355": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-354": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-353": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-352": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-351": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-350": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-349": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-348": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-347": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-346": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-345": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-344": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-343": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-342": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-341": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-340": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-339": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-338": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-337": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-336": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-335": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-334": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-333": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-332": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-331": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-330": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-329": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-328": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-327": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-326": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-325": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-324": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-323": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-322": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-321": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-320": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-319": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-318": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-317": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-316": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-315": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-314": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-313": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-312": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-311": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-310": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-309": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-308": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-307": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-306": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-305": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-304": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-303": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-302": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-301": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-300": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-299": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-298": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-297": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-296": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-295": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-294": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-293": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-292": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-291": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-290": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-289": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-288": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-287": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-286": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-285": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-284": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-283": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-282": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-281": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-280": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-279": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-278": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-277": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-276": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-275": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-274": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-273": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-272": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-271": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-270": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-269": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-268": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-267": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-266": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-265": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-264": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-263": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-262": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-261": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-260": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-259": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-258": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-257": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-256": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-255": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-254": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-253": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-252": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-251": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-250": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-249": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-248": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-247": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-246": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-245": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-244": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-243": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-242": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-241": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-240": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-239": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-238": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-237": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-236": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-235": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-234": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-233": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-232": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-231": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-230": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-229": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-228": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-227": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-226": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-225": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-224": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-223": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-222": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-221": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-220": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-219": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-218": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-217": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-216": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-215": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-214": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-213": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-212": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-211": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-210": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-209": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-208": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-207": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-206": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-205": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-204": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-203": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-202": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-201": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-200": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-199": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-198": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-197": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-196": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-195": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-194": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-193": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-192": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-191": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-190": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-189": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-188": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-187": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-186": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-185": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-184": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-183": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-182": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-181": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-180": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-179": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-178": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-177": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-176": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-175": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-174": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-173": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-172": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-171": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-170": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-169": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-168": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-167": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-166": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-165": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-164": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-163": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-162": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-161": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-160": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-159": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-158": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-157": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-156": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-155": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-154": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-153": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-152": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-151": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-150": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-149": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-148": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-147": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-146": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-145": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-144": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-143": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-142": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-141": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-140": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-139": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-138": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-137": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-136": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-135": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-134": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-133": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-132": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-131": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-130": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-129": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-128": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-127": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-126": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-125": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-124": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-123": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-122": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-121": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-120": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-119": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-118": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-117": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-116": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-115": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-114": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-113": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-112": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-111": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-110": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-109": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-108": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-107": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-106": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-105": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-104": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-103": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-102": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-101": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-100": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-99": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-98": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-97": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-96": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-95": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-94": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-93": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-92": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-91": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-90": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-89": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-88": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-87": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-86": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-85": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-84": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-83": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-82": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-81": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-80": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-79": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-78": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-77": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-76": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-75": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-74": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-73": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-72": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-71": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-70": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-69": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-68": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-67": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-66": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-65": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-64": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-63": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-62": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-61": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-60": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-59": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-58": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-57": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-56": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-55": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-54": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-53": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-52": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-51": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-50": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-49": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-48": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-47": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-46": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-45": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-44": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-43": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-42": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-41": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-40": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-39": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-38": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-37": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-36": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-35": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-34": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-33": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-32": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-31": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-30": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-29": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-28": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-27": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-26": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-25": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-24": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-23": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-22": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-21": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-20": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-19": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-18": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-17": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-16": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-15": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-14": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-13": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-12": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-11": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-10": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-9": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-8": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-7": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-6": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-5": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-4": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-3": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-2": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-1": { "type": "keyword", "script": { "source": "emit('nice')" } }, + "my-runtime-field-0": { "type": "keyword", "script": { "source": "emit('nice')" } } }, "properties": { "@timestamp": { diff --git a/x-pack/test/functional/fixtures/kbn_archiver/global_search/basic.json b/x-pack/test/functional/fixtures/kbn_archiver/global_search/basic.json index 49f26e7429870..081589750929a 100644 --- a/x-pack/test/functional/fixtures/kbn_archiver/global_search/basic.json +++ b/x-pack/test/functional/fixtures/kbn_archiver/global_search/basic.json @@ -66,7 +66,8 @@ "attributes": { "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", "timeFieldName": "@timestamp", - "title": "logstash-*" + "title": "logstash-*", + "name": "logstash-*" }, "coreMigrationVersion": "8.4.0", "id": "logstash-*", diff --git a/x-pack/test/functional/fixtures/kbn_archiver/kibana_scripted_fields_on_logstash.json b/x-pack/test/functional/fixtures/kbn_archiver/kibana_scripted_fields_on_logstash.json new file mode 100644 index 0000000000000..b9316cd311b19 --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/kibana_scripted_fields_on_logstash.json @@ -0,0 +1,35 @@ +{ + "attributes": { + "fieldFormatMap": "{\"sharedFail\":{\"id\":\"string\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:5620\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}}}", + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@message\"}}},{\"name\":\"@tags\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@tags\"}}},{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"agent\"}}},{\"name\":\"bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"extension\"}}},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"headings\"}}},{\"name\":\"host\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"host\"}}},{\"name\":\"id\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"index\"}}},{\"name\":\"ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"links\"}}},{\"name\":\"machine.os\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"machine.os\"}}},{\"name\":\"machine.ram\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:section\"}}},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:tag\"}}},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:description\"}}},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image\"}}},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:height\"}}},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:width\"}}},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:site_name\"}}},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:title\"}}},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:type\"}}},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:url\"}}},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:card\"}}},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:description\"}}},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:image\"}}},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:site\"}}},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:title\"}}},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.url\"}}},{\"name\":\"request\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"request\"}}},{\"name\":\"response\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"response\"}}},{\"name\":\"spaces\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"spaces\"}}},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"url\"}}},{\"name\":\"utc_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"xss\"}}},{\"name\":\"sharedFail\",\"type\":\"string\",\"count\":1,\"scripted\":true,\"script\":\"if (doc['response.raw'].value == '200') { return 'good ' + doc['url.raw'].value } else { return 'bad ' + doc['machine.os.raw'].value } \",\"lang\":\"painless\",\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]", + "timeFieldName": "@timestamp", + "title": "logsta*" + }, + "coreMigrationVersion": "8.4.0", + "id": "da2aebe0-913d-11ea-bf44-c796fb3350db", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2020-05-08T15:09:15.796Z", + "version": "WzE1LDJd" +} + +{ + "attributes": { + "fieldFormatMap": "{\"goodScript\":{\"id\":\"string\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:5620\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}},\"goodScript2\":{\"id\":\"string\",\"params\":{\"parsedUrl\":{\"origin\":\"http://localhost:5620\",\"pathname\":\"/app/kibana\",\"basePath\":\"\"}}}}", + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@message\"}}},{\"name\":\"@tags\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"@tags\"}}},{\"name\":\"@timestamp\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"agent\"}}},{\"name\":\"bytes\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"extension\"}}},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"esTypes\":[\"geo_point\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"headings\"}}},{\"name\":\"host\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"host\"}}},{\"name\":\"id\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"index\"}}},{\"name\":\"ip\",\"type\":\"ip\",\"esTypes\":[\"ip\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"links\"}}},{\"name\":\"machine.os\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"machine.os\"}}},{\"name\":\"machine.ram\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"esTypes\":[\"double\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"esTypes\":[\"integer\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:section\"}}},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.article:tag\"}}},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:description\"}}},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image\"}}},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:height\"}}},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:image:width\"}}},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:site_name\"}}},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:title\"}}},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:type\"}}},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.og:url\"}}},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:card\"}}},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:description\"}}},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:image\"}}},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:site\"}}},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.twitter:title\"}}},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"relatedContent.url\"}}},{\"name\":\"request\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"request\"}}},{\"name\":\"response\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"response\"}}},{\"name\":\"spaces\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"spaces\"}}},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"url\"}}},{\"name\":\"utc_time\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"xss\"}}},{\"name\":\"goodScript\",\"type\":\"string\",\"count\":1,\"scripted\":true,\"script\":\"if (doc['response.raw'].value == '200') { if (doc['url.raw'].size() > 0) { return 'good ' + doc['url.raw'].value } else { return 'good' } } else { if (doc['machine.os.raw'].size() > 0) { return 'bad ' + doc['machine.os.raw'].value } else { return 'bad' } }\",\"lang\":\"painless\",\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"goodScript2\",\"type\":\"string\",\"count\":1,\"scripted\":true,\"script\":\"if (doc['url.raw'].size() > 0) { String tempString = \\\"\\\"; for ( int i = (doc['url.raw'].value.length() - 1); i >= 0 ; i--) { tempString = tempString + (doc['url.raw'].value).charAt(i); } return tempString; } else { return \\\"emptyUrl\\\"; }\",\"lang\":\"painless\",\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]", + "timeFieldName": "@timestamp", + "title": "logstash-*" + }, + "coreMigrationVersion": "8.4.0", + "id": "eddf62c0-85bb-11ea-a555-0b6139dddc19", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2020-04-23T23:41:56.266Z", + "version": "WzksMl0=" +} \ No newline at end of file diff --git a/x-pack/test/functional/fixtures/kbn_archiver/lens/reporting.json b/x-pack/test/functional/fixtures/kbn_archiver/lens/reporting.json new file mode 100644 index 0000000000000..5c9d8661a1154 --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/lens/reporting.json @@ -0,0 +1,491 @@ +{ + "attributes": { + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "@timestamp", + "title": "logstash-*" + }, + "coreMigrationVersion": "8.4.0", + "id": "logstash-*", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2018-12-21T00:43:07.096Z", + "version": "WzE2LDJd" +} + +{ + "attributes": { + "state": { + "datasourceStates": { + "indexpattern": { + "layers": { + "bd23934e-5c70-4758-bd17-3390aab0e84c": { + "columnOrder": [ + "b6865367-27d4-449f-97ce-463a82f3a762", + "fd996842-70d7-4ad0-9a5a-3137a3d6b35a" + ], + "columns": { + "b6865367-27d4-449f-97ce-463a82f3a762": { + "dataType": "date", + "isBucketed": true, + "label": "Date histogram of @timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + }, + "fd996842-70d7-4ad0-9a5a-3137a3d6b35a": { + "dataType": "number", + "isBucketed": false, + "label": "Count of documents", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + } + } + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "accessors": [ + "fd996842-70d7-4ad0-9a5a-3137a3d6b35a" + ], + "layerId": "bd23934e-5c70-4758-bd17-3390aab0e84c", + "layerType": "data", + "position": "top", + "seriesType": "bar_stacked", + "showGridlines": false, + "xAccessor": "b6865367-27d4-449f-97ce-463a82f3a762" + } + ], + "legend": { + "isVisible": true, + "legendSize": "auto", + "position": "right" + }, + "preferredSeriesType": "bar_stacked" + } + }, + "title": "Barbar", + "visualizationType": "lnsXY" + }, + "coreMigrationVersion": "8.4.0", + "id": "74b0f140-e523-11e9-9af5-2b261e1eb063", + "migrationVersion": { + "lens": "8.3.0" + }, + "references": [ + { + "id": "logstash-*", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "logstash-*", + "name": "indexpattern-datasource-layer-bd23934e-5c70-4758-bd17-3390aab0e84c", + "type": "index-pattern" + } + ], + "type": "lens", + "updated_at": "2019-10-16T00:43:01.616Z", + "version": "WzI2LDJd" +} + +{ + "attributes": { + "state": { + "datasourceStates": { + "indexpattern": { + "layers": { + "c61a8afb-a185-4fae-a064-fb3846f6c451": { + "columnOrder": [ + "2cd09808-3915-49f4-b3b0-82767eba23f7" + ], + "columns": { + "2cd09808-3915-49f4-b3b0-82767eba23f7": { + "dataType": "number", + "isBucketed": false, + "label": "Maximum of bytes", + "operationType": "max", + "scale": "ratio", + "sourceField": "bytes" + }, + "d3e62a7a-c259-4fff-a2fc-eebf20b7008a": { + "dataType": "number", + "isBucketed": false, + "label": "Minimum of bytes", + "operationType": "min", + "scale": "ratio", + "sourceField": "bytes" + }, + "d6e40cea-6299-43b4-9c9d-b4ee305a2ce8": { + "dataType": "date", + "isBucketed": true, + "label": "Date Histogram of @timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + } + } + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "accessor": "2cd09808-3915-49f4-b3b0-82767eba23f7", + "layerId": "c61a8afb-a185-4fae-a064-fb3846f6c451", + "layerType": "data", + "layers": [ + { + "accessors": [ + "d3e62a7a-c259-4fff-a2fc-eebf20b7008a", + "26ef70a9-c837-444c-886e-6bd905ee7335" + ], + "layerId": "c61a8afb-a185-4fae-a064-fb3846f6c451", + "layerType": "data", + "seriesType": "area", + "splitAccessor": "54cd64ed-2a44-4591-af84-b2624504569a", + "xAccessor": "d6e40cea-6299-43b4-9c9d-b4ee305a2ce8" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "area", + "size": "xl", + "textAlign": "center", + "titlePosition": "bottom" + } + }, + "title": "Artistpreviouslyknownaslens", + "visualizationType": "lnsMetric" + }, + "coreMigrationVersion": "8.4.0", + "id": "76fc4200-cf44-11e9-b933-fd84270f3ac1", + "migrationVersion": { + "lens": "8.3.0" + }, + "references": [ + { + "id": "logstash-*", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "logstash-*", + "name": "indexpattern-datasource-layer-c61a8afb-a185-4fae-a064-fb3846f6c451", + "type": "index-pattern" + } + ], + "type": "lens", + "updated_at": "2019-09-04T19:40:58.862Z", + "version": "WzI0LDJd" +} + +{ + "attributes": { + "state": { + "datasourceStates": { + "indexpattern": { + "layers": { + "b0a1929e-e26a-444d-a6e9-f65baafcd025": { + "columnOrder": [ + "99513d8e-9102-43b1-bc04-e78629c1c749" + ], + "columns": { + "99513d8e-9102-43b1-bc04-e78629c1c749": { + "dataType": "number", + "isBucketed": false, + "label": "Average of bytes", + "operationType": "average", + "scale": "ratio", + "sourceField": "bytes" + } + } + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "accessor": "99513d8e-9102-43b1-bc04-e78629c1c749", + "layerId": "b0a1929e-e26a-444d-a6e9-f65baafcd025", + "layerType": "data", + "size": "xl", + "textAlign": "center", + "titlePosition": "bottom" + } + }, + "title": "Numbytes", + "visualizationType": "lnsMetric" + }, + "coreMigrationVersion": "8.4.0", + "id": "84320f00-e523-11e9-9af5-2b261e1eb063", + "migrationVersion": { + "lens": "8.3.0" + }, + "references": [ + { + "id": "logstash-*", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "logstash-*", + "name": "indexpattern-datasource-layer-b0a1929e-e26a-444d-a6e9-f65baafcd025", + "type": "index-pattern" + } + ], + "type": "lens", + "updated_at": "2019-10-16T00:43:13.714Z", + "version": "WzI3LDJd" +} + +{ + "attributes": { + "state": { + "datasourceStates": { + "indexpattern": { + "layers": { + "44fc2bcf-c8ce-4380-b060-1ef61c955818": { + "columnOrder": [ + "729e25e7-fa29-4a94-942b-41984c6d592c", + "0f744a83-1782-4494-9e98-ff0631fc6ef9" + ], + "columns": { + "0f744a83-1782-4494-9e98-ff0631fc6ef9": { + "dataType": "number", + "isBucketed": false, + "label": "Count of documents", + "operationType": "count", + "scale": "ratio", + "sourceField": "___records___" + }, + "729e25e7-fa29-4a94-942b-41984c6d592c": { + "dataType": "date", + "isBucketed": true, + "label": "Date histogram of @timestamp", + "operationType": "date_histogram", + "params": { + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + } + } + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "729e25e7-fa29-4a94-942b-41984c6d592c" + }, + { + "columnId": "0f744a83-1782-4494-9e98-ff0631fc6ef9" + }, + { + "columnId": "c4e89ccb-f85c-490c-ac01-aa73a0bcffc7" + } + ], + "layerId": "44fc2bcf-c8ce-4380-b060-1ef61c955818", + "layerType": "data", + "rowHeight": "single", + "rowHeightLines": 1 + } + }, + "title": "Tableytable", + "visualizationType": "lnsDatatable" + }, + "coreMigrationVersion": "8.4.0", + "id": "9325b9d0-e523-11e9-9af5-2b261e1eb063", + "migrationVersion": { + "lens": "8.3.0" + }, + "references": [ + { + "id": "logstash-*", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "logstash-*", + "name": "indexpattern-datasource-layer-44fc2bcf-c8ce-4380-b060-1ef61c955818", + "type": "index-pattern" + } + ], + "type": "lens", + "updated_at": "2019-10-16T00:43:27.907Z", + "version": "WzI4LDJd" +} + +{ + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}" + }, + "optionsJSON": "{\"useMargins\":true,\"hidePanelTitles\":false}", + "panelsJSON": "[{\"version\":\"8.0.0\",\"type\":\"lens\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"e5966143-f050-40eb-b4e7-f94469c1426c\"},\"panelIndex\":\"e5966143-f050-40eb-b4e7-f94469c1426c\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_e5966143-f050-40eb-b4e7-f94469c1426c\"},{\"version\":\"8.0.0\",\"type\":\"lens\",\"gridData\":{\"w\":24,\"h\":15,\"x\":24,\"y\":0,\"i\":\"f9ff2513-2de9-4944-a8d1-a9fead4b020d\"},\"panelIndex\":\"f9ff2513-2de9-4944-a8d1-a9fead4b020d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f9ff2513-2de9-4944-a8d1-a9fead4b020d\"},{\"version\":\"8.0.0\",\"type\":\"lens\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":15,\"i\":\"b62d7d36-83ca-415b-8971-34d891b09a1a\"},\"panelIndex\":\"b62d7d36-83ca-415b-8971-34d891b09a1a\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_b62d7d36-83ca-415b-8971-34d891b09a1a\"}]", + "timeRestore": false, + "title": "Lens reportz", + "version": 1 + }, + "coreMigrationVersion": "8.4.0", + "id": "c27849f0-e523-11e9-9af5-2b261e1eb063", + "migrationVersion": { + "dashboard": "8.3.0" + }, + "references": [ + { + "id": "74b0f140-e523-11e9-9af5-2b261e1eb063", + "name": "e5966143-f050-40eb-b4e7-f94469c1426c:panel_e5966143-f050-40eb-b4e7-f94469c1426c", + "type": "lens" + }, + { + "id": "84320f00-e523-11e9-9af5-2b261e1eb063", + "name": "f9ff2513-2de9-4944-a8d1-a9fead4b020d:panel_f9ff2513-2de9-4944-a8d1-a9fead4b020d", + "type": "lens" + }, + { + "id": "9325b9d0-e523-11e9-9af5-2b261e1eb063", + "name": "b62d7d36-83ca-415b-8971-34d891b09a1a:panel_b62d7d36-83ca-415b-8971-34d891b09a1a", + "type": "lens" + } + ], + "type": "dashboard", + "updated_at": "2019-10-02T14:48:56.079Z", + "version": "WzI1LDJd" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "A Pie", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"A Pie\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"dimensions\":{\"metric\":{\"accessor\":0,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"count\"}},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true,\"legendDisplay\":\"show\",\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.4.0", + "id": "i-exist", + "migrationVersion": { + "visualization": "8.3.0" + }, + "references": [ + { + "id": "logstash-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2019-01-22T19:32:31.206Z", + "version": "WzE5LDJd" +} + +{ + "attributes": { + "timeFieldName": "@timestamp", + "title": "logs*" + }, + "coreMigrationVersion": "7.17.2", + "id": "b15b1d40-a8bb-11e9-98cf-2bb06ef63e0b", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2018-12-21T00:43:07.096Z", + "version": "WzEwLDJd" +} + +{ + "attributes": { + "description": "Ok responses for jpg files", + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "index": "c9035c4f-054f-47da-b8e6-78733a4573ce", + "key": "extension.raw", + "negate": false, + "params": { + "query": "jpg" + }, + "type": "phrase", + "value": "jpg" + }, + "query": { + "match": { + "extension.raw": { + "query": "jpg", + "type": "phrase" + } + } + } + } + ], + "query": { + "language": "kuery", + "query": "response:200" + }, + "title": "OKJpgs" + }, + "coreMigrationVersion": "8.4.0", + "id": "okjpgs", + "migrationVersion": { + "query": "8.0.0" + }, + "references": [ + { + "id": "b15b1d40-a8bb-11e9-98cf-2bb06ef63e0b", + "name": "c9035c4f-054f-47da-b8e6-78733a4573ce", + "type": "index-pattern" + } + ], + "type": "query", + "updated_at": "2019-07-17T17:54:26.378Z", + "version": "WzIyLDJd" +} diff --git a/x-pack/test/functional/page_objects/gis_page.ts b/x-pack/test/functional/page_objects/gis_page.ts index e1b55d5eefe05..8e5e78a6154e7 100644 --- a/x-pack/test/functional/page_objects/gis_page.ts +++ b/x-pack/test/functional/page_objects/gis_page.ts @@ -302,6 +302,11 @@ export class GisPageObject extends FtrService { await this.testSubjects.click('layerVisibilityToggleButton'); } + // In 8.4, EMS basemap layers no longer use EMS tile service name, instead using "Basemap" + async toggleEmsBasemapLayerVisibility() { + await this.toggleLayerVisibility('Basemap'); + } + async openLegend() { const isOpen = await this.testSubjects.exists('mapLayerTOC'); if (isOpen === false) { diff --git a/x-pack/test/functional/page_objects/infra_home_page.ts b/x-pack/test/functional/page_objects/infra_home_page.ts index 21b29bd4d16fd..c30b6ed698f35 100644 --- a/x-pack/test/functional/page_objects/infra_home_page.ts +++ b/x-pack/test/functional/page_objects/infra_home_page.ts @@ -330,7 +330,7 @@ export function InfraHomePageProvider({ getService, getPageObjects }: FtrProvide }, async waitForTourStep(tourStep: string) { - await retry.waitFor('tour step', () => testSubjects.exists(tourStep)); + await retry.waitForWithTimeout('tour step', 5000, () => testSubjects.exists(tourStep)); }, async ensureTourStepIsClosed(tourStep: string) { diff --git a/x-pack/test/functional/services/ml/job_table.ts b/x-pack/test/functional/services/ml/job_table.ts index fe60073bd3a33..cc06c186a3cc8 100644 --- a/x-pack/test/functional/services/ml/job_table.ts +++ b/x-pack/test/functional/services/ml/job_table.ts @@ -366,6 +366,17 @@ export function MachineLearningJobTableProvider( ); } + public async assertJobActionResetJobButtonEnabled(jobId: string, expectedValue: boolean) { + await this.ensureJobActionsMenuOpen(jobId); + const isEnabled = await testSubjects.isEnabled('mlActionButtonResetJob'); + expect(isEnabled).to.eql( + expectedValue, + `Expected "reset job" action button for AD job '${jobId}' to be '${ + expectedValue ? 'enabled' : 'disabled' + }' (got '${isEnabled ? 'enabled' : 'disabled'}')` + ); + } + public async assertJobActionCloneJobButtonEnabled(jobId: string, expectedValue: boolean) { await this.ensureJobActionsMenuOpen(jobId); const isEnabled = await testSubjects.isEnabled('mlActionButtonCloneJob'); @@ -377,6 +388,20 @@ export function MachineLearningJobTableProvider( ); } + public async assertJobActionViewDatafeedCountsButtonEnabled( + jobId: string, + expectedValue: boolean + ) { + await this.ensureJobActionsMenuOpen(jobId); + const isEnabled = await testSubjects.isEnabled('mlActionButtonViewDatafeedChart'); + expect(isEnabled).to.eql( + expectedValue, + `Expected "view datafeed counts" action button for AD job '${jobId}' to be '${ + expectedValue ? 'enabled' : 'disabled' + }' (got '${isEnabled ? 'enabled' : 'disabled'}')` + ); + } + public async assertJobActionEditJobButtonEnabled(jobId: string, expectedValue: boolean) { await this.ensureJobActionsMenuOpen(jobId); const isEnabled = await testSubjects.isEnabled('mlActionButtonEditJob'); diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/attachment_framework.ts b/x-pack/test/functional_with_es_ssl/apps/cases/attachment_framework.ts index 7e56bc0fa6ae3..5a5a48af9b4b0 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/attachment_framework.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/attachment_framework.ts @@ -5,17 +5,70 @@ * 2.0. */ +import type SuperTest from 'supertest'; import { ExternalReferenceStorageType, CommentType, CaseResponse, + CommentRequest, } from '@kbn/cases-plugin/common/api'; +import { expect } from 'expect'; import { FtrProviderContext } from '../../ftr_provider_context'; +const createLogStashDataView = async ( + supertest: SuperTest.SuperTest +): Promise<{ data_view: { id: string } }> => { + const { body } = await supertest + .post(`/api/data_views/data_view`) + .set('kbn-xsrf', 'foo') + .send({ data_view: { title: 'logstash-*', name: 'logstash', timeFieldName: '@timestamp' } }) + .expect(200); + + return body; +}; + +const deleteLogStashDataView = async ( + supertest: SuperTest.SuperTest, + dataViewId: string +): Promise => { + await supertest + .delete(`/api/saved_objects/index-pattern/${dataViewId}`) + .query({ force: true }) + .set('kbn-xsrf', 'foo') + .send() + .expect(200); +}; + export default ({ getPageObject, getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + const esArchiver = getService('esArchiver'); const header = getPageObject('header'); const testSubjects = getService('testSubjects'); const cases = getService('cases'); + const find = getService('find'); + + const createAttachmentAndNavigate = async (attachment: CommentRequest) => { + const caseData = await cases.api.createCase({ + title: `Registered attachment of type ${attachment.type}`, + }); + const caseWithAttachment = await cases.api.createAttachment({ + caseId: caseData.id, + params: attachment, + }); + + await cases.navigation.navigateToApp(); + await cases.casesTable.waitForCasesToBeListed(); + await cases.casesTable.goToFirstListedCase(); + await header.waitUntilLoadingHasFinished(); + + return caseWithAttachment; + }; + + const validateAttachment = async (type: string, attachmentId?: string) => { + await testSubjects.existOrFail(`comment-${type}-.test`); + await testSubjects.existOrFail(`copy-link-${attachmentId}`); + await testSubjects.existOrFail('test-attachment-action'); + }; /** * Attachment types are being registered in @@ -26,23 +79,14 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { let caseWithAttachment: CaseResponse; before(async () => { - const caseData = await cases.api.createCase({ title: 'External references' }); - caseWithAttachment = await cases.api.createAttachment({ - caseId: caseData.id, - params: { - type: CommentType.externalReference, - externalReferenceId: 'my-id', - externalReferenceStorage: { type: ExternalReferenceStorageType.elasticSearchDoc }, - externalReferenceAttachmentTypeId: '.test', - externalReferenceMetadata: null, - owner: 'cases', - }, + caseWithAttachment = await createAttachmentAndNavigate({ + type: CommentType.externalReference, + externalReferenceId: 'my-id', + externalReferenceStorage: { type: ExternalReferenceStorageType.elasticSearchDoc }, + externalReferenceAttachmentTypeId: '.test', + externalReferenceMetadata: null, + owner: 'cases', }); - - await cases.navigation.navigateToApp(); - await cases.casesTable.waitForCasesToBeListed(); - await cases.casesTable.goToFirstListedCase(); - await header.waitUntilLoadingHasFinished(); }); after(async () => { @@ -51,11 +95,110 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { it('renders an external reference attachment type correctly', async () => { const attachmentId = caseWithAttachment?.comments?.[0].id; - await testSubjects.existOrFail('comment-external-reference-.test'); - await testSubjects.existOrFail(`copy-link-${attachmentId}`); - await testSubjects.existOrFail('test-attachment-action'); + await validateAttachment(CommentType.externalReference, attachmentId); await testSubjects.existOrFail('test-attachment-content'); }); }); + + describe('Persistable state attachments', () => { + const getLensState = (dataViewId: string) => ({ + title: '', + visualizationType: 'lnsXY', + type: 'lens', + references: [ + { + type: 'index-pattern', + id: dataViewId, + name: 'indexpattern-datasource-layer-85863a23-73a0-4e11-9774-70f77b9a5898', + }, + ], + state: { + visualization: { + legend: { isVisible: true, position: 'right' }, + valueLabels: 'hide', + fittingFunction: 'None', + axisTitlesVisibilitySettings: { x: true, yLeft: true, yRight: true }, + tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true }, + labelsOrientation: { x: 0, yLeft: 0, yRight: 0 }, + gridlinesVisibilitySettings: { x: true, yLeft: true, yRight: true }, + preferredSeriesType: 'bar_stacked', + layers: [ + { + layerId: '85863a23-73a0-4e11-9774-70f77b9a5898', + accessors: ['63810bd4-8481-4aab-822a-532d8513a8b1'], + position: 'top', + seriesType: 'bar_stacked', + showGridlines: false, + layerType: 'data', + xAccessor: 'ab807e89-c453-415b-8eb4-3986de52c923', + }, + ], + }, + query: { query: '', language: 'kuery' }, + filters: [], + datasourceStates: { + indexpattern: { + layers: { + '85863a23-73a0-4e11-9774-70f77b9a5898': { + columns: { + 'ab807e89-c453-415b-8eb4-3986de52c923': { + label: '@timestamp', + dataType: 'date', + operationType: 'date_histogram', + sourceField: '@timestamp', + isBucketed: true, + scale: 'interval', + params: { interval: 'auto', includeEmptyRows: true, dropPartials: false }, + }, + '63810bd4-8481-4aab-822a-532d8513a8b1': { + label: 'Median of id', + dataType: 'number', + operationType: 'median', + sourceField: 'id', + isBucketed: false, + scale: 'ratio', + params: { emptyAsNull: true }, + }, + }, + columnOrder: [ + 'ab807e89-c453-415b-8eb4-3986de52c923', + '63810bd4-8481-4aab-822a-532d8513a8b1', + ], + incompleteColumns: {}, + }, + }, + }, + }, + }, + }); + + let caseWithAttachment: CaseResponse; + let dataViewId = ''; + + before(async () => { + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); + const res = await createLogStashDataView(supertest); + dataViewId = res.data_view.id; + + caseWithAttachment = await createAttachmentAndNavigate({ + type: CommentType.persistableState, + persistableStateAttachmentTypeId: '.test', + persistableStateAttachmentState: getLensState(dataViewId), + owner: 'cases', + }); + }); + + after(async () => { + await cases.api.deleteAllCases(); + await deleteLogStashDataView(supertest, dataViewId); + await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional'); + }); + + it('renders a persistable attachment type correctly', async () => { + const attachmentId = caseWithAttachment?.comments?.[0].id; + await validateAttachment(CommentType.persistableState, attachmentId); + expect(await find.existsByCssSelector('.lnsExpressionRenderer')).toBe(true); + }); + }); }); }; diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/kibana.json b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/kibana.json index f9263695b2483..86f25f410fee7 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/kibana.json +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/kibana.json @@ -3,7 +3,7 @@ "owner": { "name": "Response Ops", "githubTeam": "response-ops" }, "version": "1.0.0", "kibanaVersion": "kibana", - "requiredPlugins": ["cases"], + "requiredPlugins": ["cases", "embeddable", "lens"], "server": true, "ui": true } diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/attachments/external_references_content.tsx b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/attachments/external_references_content.tsx index 6961539982f80..84e51ce85fed4 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/attachments/external_references_content.tsx +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/attachments/external_references_content.tsx @@ -13,7 +13,7 @@ const dg = new DataGenerator(); const data1 = dg.generateGroupedSeries(20, 1); const data2 = dg.generateGroupedSeries(20, 5); -const AttachmentContent: React.FC = () => { +const AttachmentContent: React.FC = (props) => { return ( diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/attachments/persistable_state.tsx b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/attachments/persistable_state.tsx new file mode 100644 index 0000000000000..f669406a2795a --- /dev/null +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/attachments/persistable_state.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { + PersistableStateAttachmentType, + PersistableStateAttachmentViewProps, +} from '@kbn/cases-plugin/public/client/attachment_framework/types'; +import { EuiButtonIcon } from '@elastic/eui'; +import { EmbeddableComponentProps, TypedLensByValueInput } from '@kbn/lens-plugin/public'; + +const AttachmentActions: React.FC = () => { + return ( + {}} + iconType="arrowRight" + aria-label="See attachment" + /> + ); +}; + +const getLazyComponent = ( + EmbeddableComponent: React.ComponentType +): React.LazyExoticComponent> => + React.lazy(() => { + return Promise.resolve().then(() => { + return { + default: React.memo((props: PersistableStateAttachmentViewProps) => { + const { persistableStateAttachmentState } = props; + const attributes = + persistableStateAttachmentState as unknown as TypedLensByValueInput['attributes']; + + return ( + + ); + }), + }; + }); + }); + +export const getPersistableStateAttachmentRegular = ( + EmbeddableComponent: React.ComponentType +): PersistableStateAttachmentType => ({ + id: '.test', + icon: 'casesApp', + displayName: 'Test', + getAttachmentViewObject: () => ({ + type: 'regular', + event: 'added an embeddable', + timelineIcon: 'casesApp', + actions: , + children: getLazyComponent(EmbeddableComponent), + }), +}); diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/plugin.ts b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/plugin.ts index ef0ce76848ae0..a1f3a2e11e356 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/plugin.ts +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/public/plugin.ts @@ -5,9 +5,11 @@ * 2.0. */ -import { Plugin, CoreSetup } from '@kbn/core/public'; +import { Plugin, CoreSetup, CoreStart } from '@kbn/core/public'; import { CasesUiSetup } from '@kbn/cases-plugin/public/types'; +import { LensPublicStart } from '@kbn/lens-plugin/public'; import { getExternalReferenceAttachmentRegular } from './attachments/external_reference'; +import { getPersistableStateAttachmentRegular } from './attachments/persistable_state'; export type Setup = void; export type Start = void; @@ -16,11 +18,26 @@ export interface CasesExamplePublicSetupDeps { cases: CasesUiSetup; } -export class CasesFixturePlugin implements Plugin { - public setup(core: CoreSetup, { cases }: CasesExamplePublicSetupDeps) { - cases.attachmentFramework.registerExternalReference(getExternalReferenceAttachmentRegular()); +export interface CasesExamplePublicStartDeps { + lens: LensPublicStart; +} + +export class CasesFixturePlugin + implements Plugin +{ + public setup(core: CoreSetup, plugins: CasesExamplePublicSetupDeps) { + plugins.cases.attachmentFramework.registerExternalReference( + getExternalReferenceAttachmentRegular() + ); + + core.getStartServices().then(([_, depsStart]) => { + plugins.cases.attachmentFramework.registerPersistableState( + getPersistableStateAttachmentRegular(depsStart.lens.EmbeddableComponent) + ); + }); } - public start() {} + public start(core: CoreStart, plugins: CasesExamplePublicStartDeps) {} + public stop() {} } diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/server/attachments/persistable_state.ts b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/server/attachments/persistable_state.ts new file mode 100644 index 0000000000000..1371c04c185ef --- /dev/null +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/server/attachments/persistable_state.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PersistableStateAttachmentTypeSetup } from '@kbn/cases-plugin/server/attachment_framework/types'; + +export const getPersistableStateAttachmentServer = (): PersistableStateAttachmentTypeSetup => ({ + id: '.test', +}); diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/server/plugin.ts b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/server/plugin.ts index b0af6c8c54e36..fd86aa7300eb1 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/server/plugin.ts +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/server/plugin.ts @@ -5,10 +5,19 @@ * 2.0. */ +import { PluginSetupContract as CasesSetup } from '@kbn/cases-plugin/server/types'; import { Plugin, CoreSetup } from '@kbn/core/server'; +import { getPersistableStateAttachmentServer } from './attachments/persistable_state'; + +export interface CasesExamplePublicSetupDeps { + cases: CasesSetup; +} + +export class CasesFixturePlugin implements Plugin { + public setup(core: CoreSetup, { cases }: CasesExamplePublicSetupDeps) { + cases.attachmentFramework.registerPersistableState(getPersistableStateAttachmentServer()); + } -export class CasesFixturePlugin implements Plugin { - public setup(core: CoreSetup) {} public start() {} public stop() {} } diff --git a/x-pack/test/kubernetes_security/basic/tests/aggregate.ts b/x-pack/test/kubernetes_security/basic/tests/aggregate.ts index c1501c97e77e5..92d6da4655cf4 100644 --- a/x-pack/test/kubernetes_security/basic/tests/aggregate.ts +++ b/x-pack/test/kubernetes_security/basic/tests/aggregate.ts @@ -42,12 +42,13 @@ export default function aggregateTests({ getService }: FtrProviderContext) { groupBy: ORCHESTRATOR_NAMESPACE_PROPERTY, page: 0, index: MOCK_INDEX, + perPage: 10, }); expect(response.status).to.be(200); - expect(response.body.length).to.be(10); + expect(response.body.buckets.length).to.be(10); namespaces.forEach((namespace, i) => { - expect(response.body[i].key).to.be(namespace); + expect(response.body.buckets[i].key).to.be(namespace); }); }); @@ -62,8 +63,8 @@ export default function aggregateTests({ getService }: FtrProviderContext) { index: MOCK_INDEX, }); expect(response.status).to.be(200); - expect(response.body.length).to.be(1); - expect(response.body[0].key).to.be('namespace11'); + expect(response.body.buckets.length).to.be(1); + expect(response.body.buckets[0].key).to.be('namespace11'); }); it(`${AGGREGATE_ROUTE} return countBy value for each aggregation`, async () => { @@ -78,10 +79,10 @@ export default function aggregateTests({ getService }: FtrProviderContext) { index: MOCK_INDEX, }); expect(response.status).to.be(200); - expect(response.body.length).to.be(10); + expect(response.body.buckets.length).to.be(10); // when groupBy and countBy use the same field, count_by_aggs.value will always be 1 - response.body.forEach((agg: any) => { + response.body.buckets.forEach((agg: any) => { expect(agg.count_by_aggs.value).to.be(1); }); }); @@ -99,9 +100,9 @@ export default function aggregateTests({ getService }: FtrProviderContext) { sortByCount: 'desc', }); expect(response.status).to.be(200); - expect(response.body.length).to.be(10); - expect(response.body[0].count_by_aggs.value).to.be(2); - expect(response.body[1].count_by_aggs.value).to.be(1); + expect(response.body.buckets.length).to.be(10); + expect(response.body.buckets[0].count_by_aggs.value).to.be(2); + expect(response.body.buckets[1].count_by_aggs.value).to.be(1); }); it(`${AGGREGATE_ROUTE} allows a range query`, async () => { @@ -122,7 +123,7 @@ export default function aggregateTests({ getService }: FtrProviderContext) { index: MOCK_INDEX, }); expect(response.status).to.be(200); - expect(response.body.length).to.be(3); + expect(response.body.buckets.length).to.be(3); }); it(`${AGGREGATE_ROUTE} handles a bad request`, async () => { diff --git a/x-pack/test/licensing_plugin/config.public.ts b/x-pack/test/licensing_plugin/config.public.ts index a9df9f6ad1e96..a962f499d566a 100644 --- a/x-pack/test/licensing_plugin/config.public.ts +++ b/x-pack/test/licensing_plugin/config.public.ts @@ -6,8 +6,7 @@ */ import path from 'path'; -// @ts-expect-error https://github.com/elastic/kibana/issues/95679 -import { KIBANA_ROOT } from '@kbn/test'; +import { REPO_ROOT as KIBANA_ROOT } from '@kbn/utils'; import { FtrConfigProviderContext } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { diff --git a/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts b/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts index 70cac2ade3de7..2b5f0d82e4d1a 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts @@ -94,7 +94,7 @@ export default ({ getService }: FtrProviderContext) => { 'Rules table to be visible', async () => await testSubjects.exists('rulesList') ); - await find.clickByLinkText(logThresholdRuleName); + await find.clickByButtonText(logThresholdRuleName); await retry.waitFor( 'Rule details to be visible', async () => await testSubjects.exists('ruleDetails') diff --git a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts b/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts index bd5f2deaba12c..a8b96c617db58 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts @@ -21,6 +21,7 @@ export default ({ getService }: FtrProviderContext) => { expect(ruleResponse.status).to.eql(200); return ruleResponse.body.id; } + async function deleteRuleById(ruleId: string) { const ruleResponse = await supertest .delete(`${RULE_ENDPOINT}/${ruleId}`) @@ -34,8 +35,8 @@ export default ({ getService }: FtrProviderContext) => { for (const euiTableRow of tableRows) { const $ = await euiTableRow.parseDomContent(); rows.push({ - name: $.findTestSubjects('rulesTableCell-name').find('a').text(), - enabled: $.findTestSubjects('rulesTableCell-ContextStatus').find('button').attr('title'), + name: $.findTestSubjects('rulesTableCell-name').text(), + enabled: $.findTestSubjects('rulesTableCell-status').find('button').attr('title'), }); } return rows; @@ -131,9 +132,9 @@ export default ({ getService }: FtrProviderContext) => { const tableRows = await find.allByCssSelector('.euiTableRow'); const rows = await getRulesList(tableRows); expect(rows.length).to.be(2); - expect(rows[0].name).to.be('error-log'); + expect(rows[0].name).to.contain('error-log'); expect(rows[0].enabled).to.be('Enabled'); - expect(rows[1].name).to.be('uptime'); + expect(rows[1].name).to.contain('uptime'); expect(rows[1].enabled).to.be('Enabled'); }); diff --git a/x-pack/test/plugin_functional/config.ts b/x-pack/test/plugin_functional/config.ts index a21b8f406e506..361318c0992a3 100644 --- a/x-pack/test/plugin_functional/config.ts +++ b/x-pack/test/plugin_functional/config.ts @@ -7,8 +7,7 @@ import { resolve } from 'path'; import fs from 'fs'; -// @ts-expect-error https://github.com/elastic/kibana/issues/95679 -import { KIBANA_ROOT } from '@kbn/test'; +import { REPO_ROOT as KIBANA_ROOT } from '@kbn/utils'; import { FtrConfigProviderContext } from '@kbn/test'; import { services } from './services'; import { pageObjects } from './page_objects'; diff --git a/x-pack/test/plugin_functional/test_suites/global_search/global_search_providers.ts b/x-pack/test/plugin_functional/test_suites/global_search/global_search_providers.ts index 047b852612ecf..daf1821ef5c05 100644 --- a/x-pack/test/plugin_functional/test_suites/global_search/global_search_providers.ts +++ b/x-pack/test/plugin_functional/test_suites/global_search/global_search_providers.ts @@ -40,7 +40,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await kibanaServer.savedObjects.cleanStandardList(); }); - it('can search for index patterns', async () => { + it('can search for data views', async () => { const results = await findResultsWithApi('type:index-pattern logstash'); expect(results.length).to.be(1); expect(results[0].type).to.be('index-pattern'); diff --git a/x-pack/test/screenshot_creation/apps/ml_docs/data_frame_analytics/regression.ts b/x-pack/test/screenshot_creation/apps/ml_docs/data_frame_analytics/regression.ts index ea59c68088363..de3dee3a47905 100644 --- a/x-pack/test/screenshot_creation/apps/ml_docs/data_frame_analytics/regression.ts +++ b/x-pack/test/screenshot_creation/apps/ml_docs/data_frame_analytics/regression.ts @@ -123,8 +123,14 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsResults.expandFeatureImportanceSection(false); await ml.dataFrameAnalyticsResults.expandScatterplotMatrixSection(false); await ml.dataFrameAnalyticsResults.scrollAnalysisIntoView(); + await ml.dataFrameAnalyticsResults.enableResultsTablePreviewHistogramCharts(true); await mlScreenshots.removeFocusFromElement(); - await mlScreenshots.takeScreenshot('flights-regression-results', screenshotDirectories); + await mlScreenshots.takeScreenshot( + 'flights-regression-results', + screenshotDirectories, + 1500, + 1300 + ); await ml.testExecution.logTestStep('expand feature importance section and take screenshot'); await ml.dataFrameAnalyticsResults.expandFeatureImportanceSection(true); diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_telemetry.ts b/x-pack/test/security_solution_endpoint/services/endpoint_telemetry.ts index d91a772ccafac..eb93b43e83bab 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_telemetry.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_telemetry.ts @@ -7,8 +7,7 @@ import fs from 'fs'; import Path from 'path'; -// @ts-expect-error https://github.com/elastic/kibana/issues/95679 -import { KIBANA_ROOT } from '@kbn/test'; +import { REPO_ROOT as KIBANA_ROOT } from '@kbn/utils'; import { FtrProviderContext } from '../ftr_provider_context'; const TELEMETRY_API_ROOT = '/api/stats?extended=true'; diff --git a/x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts b/x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts index 334b4ce965905..db8e624ac4356 100644 --- a/x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts +++ b/x-pack/test/upgrade/apps/maps/maps_smoke_tests.ts @@ -110,7 +110,7 @@ export default function ({ await PageObjects.home.launchSampleMap('ecommerce'); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.maps.waitForLayersToLoad(); - await mapsHelper.toggleLayerVisibilityRoadMap(); + await PageObjects.maps.toggleEmsBasemapLayerVisibility(); await PageObjects.maps.toggleLayerVisibility('United Kingdom'); await PageObjects.maps.toggleLayerVisibility('France'); await PageObjects.maps.toggleLayerVisibility('United States'); @@ -138,7 +138,7 @@ export default function ({ await PageObjects.home.launchSampleMap('flights'); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.maps.waitForLayersToLoad(); - await mapsHelper.toggleLayerVisibilityRoadMap(); + await PageObjects.maps.toggleEmsBasemapLayerVisibility(); await PageObjects.timePicker.setCommonlyUsedTime('sample_data range'); await PageObjects.maps.enterFullScreen(); await PageObjects.maps.closeLegend(); @@ -162,7 +162,7 @@ export default function ({ await PageObjects.home.launchSampleMap('logs'); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.maps.waitForLayersToLoad(); - await mapsHelper.toggleLayerVisibilityRoadMap(); + await PageObjects.maps.toggleEmsBasemapLayerVisibility(); await mapsHelper.toggleLayerVisibilityTotalRequests(); await PageObjects.timePicker.setCommonlyUsedTime('sample_data range'); await PageObjects.maps.enterFullScreen(); diff --git a/x-pack/test/upgrade/services/maps_upgrade_services.ts b/x-pack/test/upgrade/services/maps_upgrade_services.ts index 28eafafc8663a..97adb3ca9ea8a 100644 --- a/x-pack/test/upgrade/services/maps_upgrade_services.ts +++ b/x-pack/test/upgrade/services/maps_upgrade_services.ts @@ -25,27 +25,6 @@ export function MapsHelper({ getPageObjects, getService }: FtrProviderContext) { } }, - // In v8.0, the default base map switched from bright to desaturated. - // https://github.com/elastic/kibana/pull/116179 - // Maps created before this change will have a base map called "Road map" - // Maps created after this change will have a base map called "Road map - desaturated" - // toggleLayerVisibilityRoadMap will toggle layer visibility for either value - async toggleLayerVisibilityRoadMap() { - const isRoadMapDesaturated = await testSubjects.exists( - 'layerTocActionsPanelToggleButtonRoad_map_-_desaturated' - ); - const isRoadMap = await testSubjects.exists('layerTocActionsPanelToggleButtonRoad_map'); - if (!isRoadMapDesaturated && !isRoadMap) { - throw new Error('Layer road map not found'); - } - if (isRoadMapDesaturated) { - await this.toggleLayerVisibility('Road map - desaturated'); - } - if (isRoadMap) { - await this.toggleLayerVisibility('Road map'); - } - }, - // In v7.16, e-commerce sample data was re-worked so that geo.src field to match country code of geo.coordinates // https://github.com/elastic/kibana/pull/110885 // Maps created before this change will have a layer called "Total Requests by Country" diff --git a/yarn.lock b/yarn.lock index 645740bce7b48..83f4084c5dbc6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1997,6 +1997,25 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@grpc/grpc-js@^1.5.9", "@grpc/grpc-js@^1.6.7": + version "1.6.7" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.6.7.tgz#4c4fa998ff719fe859ac19fe977fdef097bb99aa" + integrity sha512-eBM03pu9hd3VqDQG+kHahiG1x80RGkkqqRb1Pchcwqej/KkAH95gAvKs6laqaHCycYaPK+TKuNQnOz9UXYA8qw== + dependencies: + "@grpc/proto-loader" "^0.6.4" + "@types/node" ">=12.12.47" + +"@grpc/proto-loader@^0.6.4", "@grpc/proto-loader@^0.6.9": + version "0.6.13" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.13.tgz#008f989b72a40c60c96cd4088522f09b05ac66bc" + integrity sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g== + dependencies: + "@types/long" "^4.0.1" + lodash.camelcase "^4.3.0" + long "^4.0.0" + protobufjs "^6.11.3" + yargs "^16.2.0" + "@gulp-sourcemaps/identity-map@1.X": version "1.0.2" resolved "https://registry.yarnpkg.com/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz#1e6fe5d8027b1f285dc0d31762f566bccd73d5a9" @@ -3104,6 +3123,22 @@ version "0.0.0" uid "" +"@kbn/core-deprecations-browser-internal@link:bazel-bin/packages/core/deprecations/core-deprecations-browser-internal": + version "0.0.0" + uid "" + +"@kbn/core-deprecations-browser-mocks@link:bazel-bin/packages/core/deprecations/core-deprecations-browser-mocks": + version "0.0.0" + uid "" + +"@kbn/core-deprecations-browser@link:bazel-bin/packages/core/deprecations/core-deprecations-browser": + version "0.0.0" + uid "" + +"@kbn/core-deprecations-common@link:bazel-bin/packages/core/deprecations/core-deprecations-common": + version "0.0.0" + uid "" + "@kbn/core-doc-links-browser-internal@link:bazel-bin/packages/core/doc-links/core-doc-links-browser-internal": version "0.0.0" uid "" @@ -3284,6 +3319,10 @@ version "0.0.0" uid "" +"@kbn/core-test-helpers-http-setup-browser@link:bazel-bin/packages/core/test-helpers/core-test-helpers-http-setup-browser": + version "0.0.0" + uid "" + "@kbn/core-theme-browser-internal@link:bazel-bin/packages/core/theme/core-theme-browser-internal": version "0.0.0" uid "" @@ -3296,6 +3335,22 @@ version "0.0.0" uid "" +"@kbn/core-ui-settings-browser-internal@link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser-internal": + version "0.0.0" + uid "" + +"@kbn/core-ui-settings-browser-mocks@link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser-mocks": + version "0.0.0" + uid "" + +"@kbn/core-ui-settings-browser@link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser": + version "0.0.0" + uid "" + +"@kbn/core-ui-settings-common@link:bazel-bin/packages/core/ui-settings/core-ui-settings-common": + version "0.0.0" + uid "" + "@kbn/crypto-browser@link:bazel-bin/packages/kbn-crypto-browser": version "0.0.0" uid "" @@ -3978,61 +4033,6 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== -"@microsoft/api-documenter@7.13.68": - version "7.13.68" - resolved "https://registry.yarnpkg.com/@microsoft/api-documenter/-/api-documenter-7.13.68.tgz#c1e144764cac0684adefe78fd848d78c3f374681" - integrity sha512-cRjwK1TDyGxFGgCsRG8G0Yi3Z4akvfWgw1pWAxKFbm7ajlQQGZcHPnb+n4lKlSeQ5g/cxc7hcdw54Mvisne9Bg== - dependencies: - "@microsoft/api-extractor-model" "7.13.16" - "@microsoft/tsdoc" "0.13.2" - "@rushstack/node-core-library" "3.43.2" - "@rushstack/ts-command-line" "4.10.4" - colors "~1.2.1" - js-yaml "~3.13.1" - resolve "~1.17.0" - -"@microsoft/api-extractor-model@7.13.16": - version "7.13.16" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.13.16.tgz#1d67541ebbcea32672c5fdd9392dc1579b2fc23a" - integrity sha512-ttdxVXsTWL5dd26W1YNLe3LgDsE0EE273aZlcLe58W0opymBybCYU1Mn+OHQM8BuErrdvdN8LdpWAAbkiOEN/Q== - dependencies: - "@microsoft/tsdoc" "0.13.2" - "@microsoft/tsdoc-config" "~0.15.2" - "@rushstack/node-core-library" "3.43.2" - -"@microsoft/api-extractor@7.18.19": - version "7.18.19" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.18.19.tgz#f09afc1c210aa67e2f3f34b0a68281a12f144541" - integrity sha512-aY+/XR7PtQXtnqNPFRs3/+iVRlQJpo6uLTjO2g7PqmnMywl3GBU3bCgAlV/khZtAQbIs6Le57XxmSE6rOqbcfg== - dependencies: - "@microsoft/api-extractor-model" "7.13.16" - "@microsoft/tsdoc" "0.13.2" - "@microsoft/tsdoc-config" "~0.15.2" - "@rushstack/node-core-library" "3.43.2" - "@rushstack/rig-package" "0.3.5" - "@rushstack/ts-command-line" "4.10.4" - colors "~1.2.1" - lodash "~4.17.15" - resolve "~1.17.0" - semver "~7.3.0" - source-map "~0.6.1" - typescript "~4.4.2" - -"@microsoft/tsdoc-config@~0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz#eb353c93f3b62ab74bdc9ab6f4a82bcf80140f14" - integrity sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA== - dependencies: - "@microsoft/tsdoc" "0.13.2" - ajv "~6.12.6" - jju "~1.4.0" - resolve "~1.19.0" - -"@microsoft/tsdoc@0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz#3b0efb6d3903bd49edb073696f60e90df08efb26" - integrity sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg== - "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -4415,11 +4415,120 @@ "@mattiasbuelens/web-streams-adapter" "~0.1.0" web-streams-polyfill "~3.0.3" -"@opentelemetry/api@^1.1.0": +"@opentelemetry/api-metrics@0.30.0", "@opentelemetry/api-metrics@^0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-metrics/-/api-metrics-0.30.0.tgz#b5defd10756e81d1c7ce8669ff8a8d2465ba0be8" + integrity sha512-jSb7iiYPY+DSUKIyzfGt0a5K1QGzWY5fSWtUB8Alfi27NhQGHBeuYYC5n9MaBP/HNWw5GpEIhXGEYCF9Pf8IEg== + dependencies: + "@opentelemetry/api" "^1.0.0" + +"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.1.0.tgz#563539048255bbe1a5f4f586a4a10a1bb737f44a" integrity sha512-hf+3bwuBwtXsugA2ULBc95qxrOqP2pOekLz34BJhcAKawt94vfeNyUKpYc0lZQ/3sCP6LqRa7UAdHA7i5UODzQ== +"@opentelemetry/core@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.4.0.tgz#26839ab9e36583a174273a1e1c5b33336c163725" + integrity sha512-faq50VFEdyC7ICAOlhSi+yYZ+peznnGjTJToha9R63i9fVopzpKrkZt7AIdXUmz2+L2OqXrcJs7EIdN/oDyr5w== + dependencies: + "@opentelemetry/semantic-conventions" "1.4.0" + +"@opentelemetry/exporter-metrics-otlp-grpc@^0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.30.0.tgz#4117d07b94302ef407dc7625a1b599de308c5476" + integrity sha512-02WEAA3X7A6qveCYISr6mvg8eKl9NeNdZytQiAexzAIItW/ncN3mxmbuf8VVZHNPBe6osisSzxhPpFH3G6Gh+w== + dependencies: + "@grpc/grpc-js" "^1.5.9" + "@grpc/proto-loader" "^0.6.9" + "@opentelemetry/core" "1.4.0" + "@opentelemetry/exporter-metrics-otlp-http" "0.30.0" + "@opentelemetry/otlp-grpc-exporter-base" "0.30.0" + "@opentelemetry/otlp-transformer" "0.30.0" + "@opentelemetry/resources" "1.4.0" + "@opentelemetry/sdk-metrics-base" "0.30.0" + +"@opentelemetry/exporter-metrics-otlp-http@0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.30.0.tgz#9d87e4c3e796e14109ac83e6d4ce5bad215c2a1e" + integrity sha512-2NFR/D9jih1TtEnEyD7oIMR47yb9Kuy5v2x+Fu19vv2gTf1HOhdA+LT4SpkxH+dUixEnDw8n11XBIa/uhNfq3Q== + dependencies: + "@opentelemetry/api-metrics" "0.30.0" + "@opentelemetry/core" "1.4.0" + "@opentelemetry/otlp-exporter-base" "0.30.0" + "@opentelemetry/otlp-transformer" "0.30.0" + "@opentelemetry/resources" "1.4.0" + "@opentelemetry/sdk-metrics-base" "0.30.0" + +"@opentelemetry/exporter-prometheus@^0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.30.0.tgz#f81322d3cb000170e716bc76820600d5649be538" + integrity sha512-y0SXvpzoKR+Tk/UL6F1f7vAcCzqpCDP/cTEa+Z7sX57aEG0HDXLQiLmAgK/BHqcEN5MFQMZ+MDVDsUrvpa6/Jw== + dependencies: + "@opentelemetry/api-metrics" "0.30.0" + "@opentelemetry/core" "1.4.0" + "@opentelemetry/sdk-metrics-base" "0.30.0" + +"@opentelemetry/otlp-exporter-base@0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.30.0.tgz#5f278b3529d38311dbdfc1ebcb764f5e5126e548" + integrity sha512-+dJnj2MSd3tsk+ooEw+0bF+dJs/NjGEVnCB3/FYxnUFaW9cCBbQQyt6X3YQYtYrEx4EEiTlwrW8pUpB1tsup7A== + dependencies: + "@opentelemetry/core" "1.4.0" + +"@opentelemetry/otlp-grpc-exporter-base@0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.30.0.tgz#3fa07667ddf604a028583a2a138b8b4ba8fa9bb0" + integrity sha512-86fuhZ7Z2un3L5Kd7jbH1oEn92v9DD92teErnYRXqYB/qyO61OLxaY6WxH9KOjmbs5CgCdLQ5bvED3wWDe3r7w== + dependencies: + "@grpc/grpc-js" "^1.5.9" + "@grpc/proto-loader" "^0.6.9" + "@opentelemetry/core" "1.4.0" + "@opentelemetry/otlp-exporter-base" "0.30.0" + +"@opentelemetry/otlp-transformer@0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.30.0.tgz#d81e1ae68dfb31d66cd4ca03ca965cdaa2e2b288" + integrity sha512-BTLXyBPBlCQCG4tXYZjlso4pT+gGpnTjzkFYTPYs52fO5DMWvYHlV8ST/raOIqX7wsamiH2zeqJ9W91017MtdA== + dependencies: + "@opentelemetry/api-metrics" "0.30.0" + "@opentelemetry/core" "1.4.0" + "@opentelemetry/resources" "1.4.0" + "@opentelemetry/sdk-metrics-base" "0.30.0" + "@opentelemetry/sdk-trace-base" "1.4.0" + +"@opentelemetry/resources@1.4.0", "@opentelemetry/resources@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.4.0.tgz#5e23b0d7976158861059dec17e0ee36a35a5ab85" + integrity sha512-Q3pI5+pCM+Ur7YwK9GbG89UBipwJbfmuzSPAXTw964ZHFzSrz+JAgrETC9rqsUOYdUlj/V7LbRMG5bo72xE0Xw== + dependencies: + "@opentelemetry/core" "1.4.0" + "@opentelemetry/semantic-conventions" "1.4.0" + +"@opentelemetry/sdk-metrics-base@0.30.0", "@opentelemetry/sdk-metrics-base@^0.30.0": + version "0.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics-base/-/sdk-metrics-base-0.30.0.tgz#242d9260a89a1ac2bf1e167b3fda758f3883c769" + integrity sha512-3BDg1MYDInDyGvy+bSH8OuCX5nsue7omH6Y2eidCGTTDYRPxDmq9tsRJxnTUepoMAvWX+1sTwZ4JqTFmc1z8Mw== + dependencies: + "@opentelemetry/api-metrics" "0.30.0" + "@opentelemetry/core" "1.4.0" + "@opentelemetry/resources" "1.4.0" + lodash.merge "4.6.2" + +"@opentelemetry/sdk-trace-base@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.4.0.tgz#e54d09c1258cd53d3fe726053ed1cbda9d74f023" + integrity sha512-l7EEjcOgYlKWK0hfxz4Jtkkk2DuGiqBDWmRZf7g2Is9RVneF1IgcrbYZTKGaVfBKA7lPuVtUiQ2qTv3R+dKJrw== + dependencies: + "@opentelemetry/core" "1.4.0" + "@opentelemetry/resources" "1.4.0" + "@opentelemetry/semantic-conventions" "1.4.0" + +"@opentelemetry/semantic-conventions@1.4.0", "@opentelemetry/semantic-conventions@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.4.0.tgz#facf2c67d6063b9918d5a5e3fdf25f3a30d547b6" + integrity sha512-Hzl8soGpmyzja9w3kiFFcYJ7n5HNETpplY6cb67KR4QPlxp4FTTresO06qXHgHDhyIInmbLJXuwARjjpsKYGuQ== + "@percy/agent@^0.28.6": version "0.28.6" resolved "https://registry.yarnpkg.com/@percy/agent/-/agent-0.28.6.tgz#b220fab6ddcf63ae4e6c343108ba6955a772ce1c" @@ -4587,39 +4696,6 @@ redux-thunk "^2.3.0" reselect "^4.0.0" -"@rushstack/node-core-library@3.43.2": - version "3.43.2" - resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.43.2.tgz#f067371a94fd92ed8f9d9aa8201c5e9e17a19f0f" - integrity sha512-b7AEhSf6CvZgvuDcWMFDeKx2mQSn9AVnMQVyxNxFeHCtLz3gJicqCOlw2GOXM8HKh6PInLdil/NVCDcstwSrIw== - dependencies: - "@types/node" "12.20.24" - colors "~1.2.1" - fs-extra "~7.0.1" - import-lazy "~4.0.0" - jju "~1.4.0" - resolve "~1.17.0" - semver "~7.3.0" - timsort "~0.3.0" - z-schema "~3.18.3" - -"@rushstack/rig-package@0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@rushstack/rig-package/-/rig-package-0.3.5.tgz#7ddab0994647837bab8fdef26f990f1774d82e78" - integrity sha512-CvqWw+E81U5lRBN/lUj7Ngr/XQa/PPb2jAS5QcLP7WL+IMUl+3+Cc2qYrsDoB4zke81kz+usWGmBQpBzGMLmAA== - dependencies: - resolve "~1.17.0" - strip-json-comments "~3.1.1" - -"@rushstack/ts-command-line@4.10.4": - version "4.10.4" - resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.10.4.tgz#05142b74e5cb207d3dd9b935c82f80d7fcb68042" - integrity sha512-4T5ao4UgDb6LmiRj4GumvG3VT/p6RSMgl7TN7S58ifaAGN2GeTNBajFCDdJs9QQP0d/4tA5p0SFzT7Ps5Byirg== - dependencies: - "@types/argparse" "1.0.38" - argparse "~1.0.9" - colors "~1.2.1" - string-argv "~0.3.1" - "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -5895,11 +5971,6 @@ dependencies: "@types/glob" "*" -"@types/argparse@1.0.38": - version "1.0.38" - resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" - integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA== - "@types/aria-query@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" @@ -6723,6 +6794,22 @@ version "0.0.0" uid "" +"@types/kbn__core-deprecations-browser-internal@link:bazel-bin/packages/core/deprecations/core-deprecations-browser-internal/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-deprecations-browser-mocks@link:bazel-bin/packages/core/deprecations/core-deprecations-browser-mocks/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-deprecations-browser@link:bazel-bin/packages/core/deprecations/core-deprecations-browser/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-deprecations-common@link:bazel-bin/packages/core/deprecations/core-deprecations-common/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__core-doc-links-browser-internal@link:bazel-bin/packages/core/doc-links/core-doc-links-browser-internal/npm_module_types": version "0.0.0" uid "" @@ -6911,6 +6998,10 @@ version "0.0.0" uid "" +"@types/kbn__core-test-helpers-http-setup-browser@link:bazel-bin/packages/core/test-helpers/core-test-helpers-http-setup-browser/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__core-theme-browser-internal@link:bazel-bin/packages/core/theme/core-theme-browser-internal/npm_module_types": version "0.0.0" uid "" @@ -6923,6 +7014,22 @@ version "0.0.0" uid "" +"@types/kbn__core-ui-settings-browser-internal@link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser-internal/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-ui-settings-browser-mocks@link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser-mocks/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-ui-settings-browser@link:bazel-bin/packages/core/ui-settings/core-ui-settings-browser/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-ui-settings-common@link:bazel-bin/packages/core/ui-settings/core-ui-settings-common/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__crypto-browser@link:bazel-bin/packages/kbn-crypto-browser/npm_module_types": version "0.0.0" uid "" @@ -7331,6 +7438,11 @@ resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== +"@types/long@^4.0.1": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + "@types/lru-cache@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03" @@ -7450,12 +7562,12 @@ dependencies: moment ">=2.14.0" -"@types/moment-timezone@^0.5.12": - version "0.5.12" - resolved "https://registry.yarnpkg.com/@types/moment-timezone/-/moment-timezone-0.5.12.tgz#0fb680c03db194fe8ff4551eaeb1eec8d3d80e9f" - integrity sha512-hnHH2+Efg2vExr/dSz+IX860nSiyk9Sk4pJF2EmS11lRpMcNXeB4KBW5xcgw2QPsb9amTXdsVNEe5IoJXiT0uw== +"@types/moment-timezone@^0.5.30": + version "0.5.30" + resolved "https://registry.yarnpkg.com/@types/moment-timezone/-/moment-timezone-0.5.30.tgz#340ed45fe3e715f4a011f5cfceb7cb52aad46fc7" + integrity sha512-aDVfCsjYnAQaV/E9Qc24C5Njx1CoDjXsEgkxtp9NyXDpYu4CCbmclb6QhWloS9UTU/8YROUEEdEkWI0D7DxnKg== dependencies: - moment ">=2.14.0" + moment-timezone "*" "@types/mustache@^0.8.31": version "0.8.31" @@ -7498,7 +7610,7 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@12.20.24", "@types/node@16.11.41", "@types/node@>= 8", "@types/node@>=8.9.0", "@types/node@^10.1.0", "@types/node@^14.0.10", "@types/node@^14.14.31": +"@types/node@*", "@types/node@16.11.41", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=8.9.0", "@types/node@^10.1.0", "@types/node@^14.0.10", "@types/node@^14.14.31": version "16.11.41" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.41.tgz#88eb485b1bfdb4c224d878b7832239536aa2f813" integrity sha512-mqoYK2TnVjdkGk8qXAVGc/x9nSaTpSrFaGFm43BUH3IdoBV0nta6hYaGmdOvIMlbHJbUEVen3gvwpwovAZKNdQ== @@ -8794,7 +8906,7 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^6.11.0, ajv@^6.12.5, ajv@~6.12.6: +ajv@^6.11.0, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -9127,7 +9239,7 @@ arg@^4.1.0: resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== -argparse@^1.0.7, argparse@~1.0.9: +argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== @@ -9417,11 +9529,6 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= -ast-types@0.9.6: - version "0.9.6" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" - integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk= - ast-types@^0.13.2: version "0.13.3" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.3.tgz#50da3f28d17bdbc7969a3a2d83a0e4a72ae755a7" @@ -10703,14 +10810,6 @@ callsites@^3.1.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= - dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" - camel-case@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" @@ -11046,7 +11145,7 @@ classnames@2.2.6, classnames@2.x, classnames@^2.2.5, classnames@^2.2.6: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== -clean-css@4.2.x, clean-css@^4.2.3: +clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== @@ -11390,11 +11489,6 @@ colors@1.4.0, colors@^1.3.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -colors@~1.2.1: - version "1.2.5" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.2.5.tgz#89c7ad9a374bc030df8013241f68136ed8835afc" - integrity sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg== - colorspace@1.1.x: version "1.1.1" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.1.tgz#9ac2491e1bc6f8fb690e2176814f8d091636d972" @@ -11435,11 +11529,6 @@ commander@2, commander@^2.19.0, commander@^2.20.0, commander@^2.7.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@2.17.x: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== - commander@7, commander@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" @@ -13544,20 +13633,20 @@ domhandler@^2.3.0: dependencies: domelementtype "1" -domhandler@^4.0, domhandler@^4.2.2: +domhandler@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9" + integrity sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw== + dependencies: + domelementtype "^2.0.1" + +domhandler@^4.0.0, domhandler@^4.0, domhandler@^4.2.0, domhandler@^4.2.2: version "4.3.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== dependencies: domelementtype "^2.2.0" -domhandler@^4.0.0, domhandler@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" - integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA== - dependencies: - domelementtype "^2.2.0" - domutils@1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485" @@ -13581,7 +13670,7 @@ domutils@^1.5.1, domutils@^1.7.0: dom-serializer "0" domelementtype "1" -domutils@^2.5.2, domutils@^2.6.0, domutils@^2.7.0, domutils@^2.8.0: +domutils@^2.0.0, domutils@^2.5.2, domutils@^2.6.0, domutils@^2.7.0, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -14209,14 +14298,6 @@ es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1: d "1" es5-ext "~0.10.14" -es6-templates@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/es6-templates/-/es6-templates-0.2.3.tgz#5cb9ac9fb1ded6eb1239342b81d792bbb4078ee4" - integrity sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ= - dependencies: - recast "~0.11.12" - through "~2.3.6" - es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" @@ -14601,11 +14682,6 @@ esprima@~1.0.4: resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" integrity sha1-n1V+CPw7TSbs6d00+Pv0drYlha0= -esprima@~3.1.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - esquery@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" @@ -15104,11 +15180,6 @@ fastest-stable-stringify@^1.0.1: resolved "https://registry.yarnpkg.com/fastest-stable-stringify/-/fastest-stable-stringify-1.0.1.tgz#9122d406d4c9d98bea644a6b6853d5874b87b028" integrity sha1-kSLUBtTJ2YvqZEpraFPVh0uHsCg= -fastparse@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" - integrity sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg= - fastq@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" @@ -15676,7 +15747,7 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^7.0.0, fs-extra@^7.0.1, fs-extra@~7.0.1: +fs-extra@^7.0.0, fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -16827,7 +16898,7 @@ hdr-histogram-js@^1.2.0: base64-js "^1.2.0" pako "^1.0.3" -he@1.2.0, he@1.2.x, he@^1.2.0: +he@1.2.0, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -16974,18 +17045,17 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -html-loader@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-0.5.5.tgz#6356dbeb0c49756d8ebd5ca327f16ff06ab5faea" - integrity sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog== +html-loader@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/html-loader/-/html-loader-1.3.2.tgz#5a72ebba420d337083497c9aba7866c9e1aee340" + integrity sha512-DEkUwSd0sijK5PF3kRWspYi56XP7bTNkyg5YWSzBdjaSDmvCufep5c4Vpb3PBf6lUL0YPtLwBfy9fL0t5hBAGA== dependencies: - es6-templates "^0.2.3" - fastparse "^1.1.1" - html-minifier "^3.5.8" - loader-utils "^1.1.0" - object-assign "^4.1.1" + html-minifier-terser "^5.1.1" + htmlparser2 "^4.1.0" + loader-utils "^2.0.0" + schema-utils "^3.0.0" -html-minifier-terser@^5.0.1: +html-minifier-terser@^5.0.1, html-minifier-terser@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== @@ -16998,19 +17068,6 @@ html-minifier-terser@^5.0.1: relateurl "^0.2.7" terser "^4.6.3" -html-minifier@^3.5.8: - version "3.5.21" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" - integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== - dependencies: - camel-case "3.0.x" - clean-css "4.2.x" - commander "2.17.x" - he "1.2.x" - param-case "2.1.x" - relateurl "0.2.x" - uglify-js "3.4.x" - html-tags@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" @@ -17070,6 +17127,16 @@ htmlparser2@^3.10.0: inherits "^2.0.1" readable-stream "^3.1.1" +htmlparser2@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" + integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^3.0.0" + domutils "^2.0.0" + entities "^2.0.0" + htmlparser2@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" @@ -17368,7 +17435,7 @@ import-lazy@^2.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= -import-lazy@^4.0.0, import-lazy@~4.0.0: +import-lazy@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== @@ -17787,7 +17854,7 @@ is-color-stop@^1.0.0: rgb-regex "^1.0.1" rgba-regex "^1.0.0" -is-core-module@^2.1.0, is-core-module@^2.2.0, is-core-module@^2.6.0, is-core-module@^2.8.1: +is-core-module@^2.2.0, is-core-module@^2.6.0, is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== @@ -19121,11 +19188,6 @@ jimp@^0.14.0: "@jimp/types" "^0.14.0" regenerator-runtime "^0.13.3" -jju@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" - integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= - joi@*, joi@^17.3.0, joi@^17.4.0: version "17.4.0" resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.0.tgz#b5c2277c8519e016316e49ababd41a1908d9ef20" @@ -19233,14 +19295,6 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -js-yaml@~3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -20018,7 +20072,7 @@ lodash.flattendeep@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= -lodash.get@^4.0.0, lodash.get@^4.4.2: +lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= @@ -20138,7 +20192,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@>4.17.4, lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@~4.17.10, lodash@~4.17.15: +lodash@>4.17.4, lodash@^4.0.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@~4.17.10: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -20260,11 +20314,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3 dependencies: js-tokens "^3.0.0 || ^4.0.0" -lower-case@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= - lower-case@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" @@ -21185,10 +21234,10 @@ moment-duration-format@^2.3.2: resolved "https://registry.yarnpkg.com/moment-duration-format/-/moment-duration-format-2.3.2.tgz#5fa2b19b941b8d277122ff3f87a12895ec0d6212" integrity sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ== -moment-timezone@^0.5.27: - version "0.5.27" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.27.tgz#73adec8139b6fe30452e78f210f27b1f346b8877" - integrity sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw== +moment-timezone@*, moment-timezone@^0.5.34: + version "0.5.34" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c" + integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg== dependencies: moment ">= 2.9.0" @@ -21496,13 +21545,6 @@ nise@^1.5.2: lolex "^5.0.1" path-to-regexp "^1.7.0" -no-case@^2.2.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== - dependencies: - lower-case "^1.1.1" - no-case@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" @@ -22516,13 +22558,6 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@2.1.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= - dependencies: - no-case "^2.2.0" - param-case@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.3.tgz#4be41f8399eff621c56eebb829a5e451d9801238" @@ -23738,7 +23773,7 @@ prismjs@^1.22.0, prismjs@~1.25.0, prismjs@~1.27.0: resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== -private@^0.1.8, private@~0.1.5: +private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== @@ -23921,6 +23956,25 @@ protobufjs@6.8.8: "@types/node" "^10.1.0" long "^4.0.0" +protobufjs@^6.11.3: + version "6.11.3" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" + integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" ">=13.7.0" + long "^4.0.0" + protocol-buffers-schema@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz#00434f608b4e8df54c59e070efeefc37fb4bb859" @@ -25130,16 +25184,6 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" -recast@~0.11.12: - version "0.11.23" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3" - integrity sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM= - dependencies: - ast-types "0.9.6" - esprima "~3.1.0" - private "~0.1.5" - source-map "~0.5.0" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -25389,7 +25433,7 @@ rehype-stringify@^8.0.0: dependencies: hast-util-to-html "^7.1.1" -relateurl@0.2.x, relateurl@^0.2.7: +relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= @@ -25845,21 +25889,6 @@ resolve@^2.0.0-next.3: is-core-module "^2.2.0" path-parse "^1.0.6" -resolve@~1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - -resolve@~1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== - dependencies: - is-core-module "^2.1.0" - path-parse "^1.0.6" - responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -26329,7 +26358,7 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semve resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@~7.3.0, semver@~7.3.2: +semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@~7.3.2: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -26880,7 +26909,7 @@ source-map@0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= -source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -27332,11 +27361,6 @@ strict-uri-encode@^2.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= -string-argv@~0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" - integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== - string-length@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/string-length/-/string-length-1.0.1.tgz#56970fb1c38558e9e70b728bf3de269ac45adfac" @@ -27556,7 +27580,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1, strip-json-comments@~3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -28170,7 +28194,7 @@ through2@^4.0.2: dependencies: readable-stream "3" -"through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.6: +"through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8, through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -28217,7 +28241,7 @@ timm@^1.6.1: resolved "https://registry.yarnpkg.com/timm/-/timm-1.6.1.tgz#5f8aafc932248c76caf2c6af60542a32d3c30701" integrity sha512-hqDTYi/bWuDxL2i6T3v6nrvkAQ/1Bc060GSkVEQZp02zTSTB4CHSKsOkliequCftQaNRcjRqUZmpGWs5FfhrNg== -timsort@^0.3.0, timsort@~0.3.0: +timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= @@ -28737,7 +28761,7 @@ typescript-tuple@^2.2.1: dependencies: typescript-compare "^0.0.2" -typescript@4.6.3, typescript@^3.3.3333, typescript@^3.5.3, typescript@^4.5.5, typescript@~4.4.2: +typescript@4.6.3, typescript@^3.3.3333, typescript@^3.5.3, typescript@^4.5.5: version "4.6.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== @@ -28752,7 +28776,7 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.5.tgz#0c65f15f815aa08b560a61ce8b4db7ffc3f45376" integrity sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg== -uglify-js@3.4.x, uglify-js@^3.1.4, uglify-js@^3.14.3: +uglify-js@^3.1.4, uglify-js@^3.14.3: version "3.14.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.4.tgz#68756f17d1b90b9d289341736cb9a567d6882f90" integrity sha512-AbiSR44J0GoCeV81+oxcy/jDOElO2Bx3d0MfQCUShq7JRXaM4KtQopZsq2vFv8bCq2yMaGrw1FgygUd03RyRDA== @@ -29198,11 +29222,6 @@ update-notifier@^5.1.0: semver-diff "^3.1.1" xdg-basedir "^4.0.0" -upper-case@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -29485,11 +29504,6 @@ validator@^13.6.0, validator@^13.7.0: resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== -validator@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-8.2.0.tgz#3c1237290e37092355344fef78c231249dab77b9" - integrity sha512-Yw5wW34fSv5spzTXNkokD6S6/Oq92d8q/t14TqsS3fAiA1RYnxSFSIZ+CY3n6PGGRCq5HhJTSepQvFUS2QUDxA== - value-equal@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7" @@ -30871,7 +30885,7 @@ yargs-unparser@2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@16.2.0: +yargs@16.2.0, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -31024,17 +31038,6 @@ z-schema@^5.0.1: optionalDependencies: commander "^2.7.1" -z-schema@~3.18.3: - version "3.18.4" - resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-3.18.4.tgz#ea8132b279533ee60be2485a02f7e3e42541a9a2" - integrity sha512-DUOKC/IhbkdLKKiV89gw9DUauTV8U/8yJl1sjf6MtDmzevLKOF2duNJ495S3MFVjqZarr+qNGCPbkg4mu4PpLw== - dependencies: - lodash.get "^4.0.0" - lodash.isequal "^4.0.0" - validator "^8.0.0" - optionalDependencies: - commander "^2.7.1" - zip-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79"