From cffa9d50a465a0c7d52f403e38558bf3cd12b3ea Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 25 Jul 2023 01:07:16 -0400 Subject: [PATCH 01/29] [api-docs] 2023-07-25 Daily api_docs build (#162452) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/409 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.devdocs.json | 278 +----------------- api_docs/alerting.mdx | 4 +- api_docs/apm.mdx | 2 +- api_docs/asset_manager.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.devdocs.json | 4 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_chat.mdx | 2 +- api_docs/cloud_chat_provider.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.devdocs.json | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.devdocs.json | 4 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 3 +- api_docs/deprecations_by_plugin.mdx | 2 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.devdocs.json | 181 ++++++++++-- api_docs/discover.mdx | 4 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/ecs_data_quality_dashboard.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/exploratory_view.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.devdocs.json | 60 ++++ api_docs/field_formats.mdx | 4 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.devdocs.json | 22 +- api_docs/fleet.mdx | 4 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- api_docs/kbn_alerting_state_types.mdx | 2 +- api_docs/kbn_alerts_as_data_utils.mdx | 2 +- api_docs/kbn_alerts_ui_shared.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_analytics_shippers_gainsight.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mocks.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- .../kbn_content_management_content_editor.mdx | 2 +- ...tent_management_tabbed_table_list_view.mdx | 2 +- ...kbn_content_management_table_list_view.mdx | 2 +- ...ntent_management_table_list_view_table.mdx | 2 +- api_docs/kbn_content_management_utils.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- .../kbn_core_application_browser.devdocs.json | 10 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.devdocs.json | 96 +++--- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- ...core_saved_objects_api_server.devdocs.json | 12 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- ...kbn_core_saved_objects_server.devdocs.json | 8 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_internal.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_core_user_settings_server.mdx | 2 +- ...kbn_core_user_settings_server_internal.mdx | 2 +- .../kbn_core_user_settings_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_cypress_config.mdx | 2 +- api_docs/kbn_data_service.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_deeplinks_analytics.mdx | 2 +- api_docs/kbn_deeplinks_devtools.mdx | 2 +- api_docs/kbn_deeplinks_management.mdx | 2 +- api_docs/kbn_deeplinks_ml.mdx | 2 +- .../kbn_deeplinks_observability.devdocs.json | 2 +- api_docs/kbn_deeplinks_observability.mdx | 2 +- api_docs/kbn_deeplinks_search.mdx | 2 +- api_docs/kbn_default_nav_analytics.mdx | 2 +- api_docs/kbn_default_nav_devtools.mdx | 2 +- api_docs/kbn_default_nav_management.mdx | 2 +- api_docs/kbn_default_nav_ml.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_discover_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_dom_drag_drop.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_ecs.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_elastic_assistant.mdx | 2 +- api_docs/kbn_es.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_es_types.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_event_annotation_common.mdx | 2 +- api_docs/kbn_event_annotation_components.mdx | 2 +- api_docs/kbn_expandable_flyout.devdocs.json | 60 ++-- api_docs/kbn_expandable_flyout.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- .../kbn_ftr_common_functional_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_generate_console_definitions.mdx | 2 +- api_docs/kbn_generate_csv.mdx | 2 +- api_docs/kbn_generate_csv_types.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_i18n_react.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_infra_forge.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_management_cards_navigation.mdx | 2 +- api_docs/kbn_management_storybook_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_maps_vector_tile_utils.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_anomaly_utils.mdx | 2 +- api_docs/kbn_ml_category_validator.mdx | 2 +- .../kbn_ml_data_frame_analytics_utils.mdx | 2 +- api_docs/kbn_ml_data_grid.mdx | 2 +- api_docs/kbn_ml_date_picker.mdx | 2 +- api_docs/kbn_ml_date_utils.mdx | 2 +- api_docs/kbn_ml_error_utils.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_kibana_theme.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_number_utils.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_random_sampler_utils.mdx | 2 +- api_docs/kbn_ml_route_utils.mdx | 2 +- api_docs/kbn_ml_runtime_field_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_trained_models_utils.mdx | 2 +- api_docs/kbn_ml_url_state.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_object_versioning.mdx | 2 +- api_docs/kbn_observability_alert_details.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_osquery_io_ts_types.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_random_sampling.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_repo_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_reporting_common.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_rrule.devdocs.json | 2 +- api_docs/kbn_rrule.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_saved_objects_settings.mdx | 2 +- api_docs/kbn_security_solution_side_nav.mdx | 2 +- ...kbn_security_solution_storybook_config.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_data_table.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.mdx | 2 +- api_docs/kbn_securitysolution_grouping.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_serverless_project_switcher.mdx | 2 +- api_docs/kbn_serverless_storybook_config.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- ...ared_ux_avatar_user_profile_components.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.mdx | 2 +- ...hared_ux_button_exit_full_screen_mocks.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_chrome_navigation.mdx | 2 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_types.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_test_subj_selector.mdx | 2 +- api_docs/kbn_text_based_editor.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_unified_field_list.mdx | 2 +- api_docs/kbn_url_state.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_visualization_ui_components.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/logs_shared.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.devdocs.json | 2 +- api_docs/observability.mdx | 2 +- api_docs/observability_onboarding.mdx | 2 +- api_docs/observability_shared.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 14 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 4 +- api_docs/reporting_export_types.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- .../saved_objects_management.devdocs.json | 10 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/security_solution_ess.mdx | 2 +- api_docs/security_solution_serverless.mdx | 2 +- api_docs/serverless.mdx | 2 +- api_docs/serverless_observability.mdx | 2 +- api_docs/serverless_search.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/stack_connectors.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/text_based_languages.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_histogram.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 564 files changed, 912 insertions(+), 960 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 6333988be22ef14..65dfd6944e4360d 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 58f029c9d474e72..82e9bbb6bce1437 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 3be55cd1d487b02..8c386180e2864d6 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index 4a5ed373058a675..a6d92e8e087c772 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -1401,192 +1401,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsFilter", - "type": "Interface", - "tags": [], - "label": "BulkEditOptionsFilter", - "description": [], - "signature": [ - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.BulkEditOptionsFilter", - "text": "BulkEditOptionsFilter" - }, - "" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsFilter.filter", - "type": "CompoundType", - "tags": [], - "label": "filter", - "description": [], - "signature": [ - "string | ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.KueryNode", - "text": "KueryNode" - }, - " | undefined" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsFilter.operations", - "type": "Array", - "tags": [], - "label": "operations", - "description": [], - "signature": [ - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.BulkEditOperation", - "text": "BulkEditOperation" - }, - "[]" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsFilter.paramsModifier", - "type": "Function", - "tags": [], - "label": "paramsModifier", - "description": [], - "signature": [ - "RuleParamsModifier", - " | undefined" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsFilter.shouldIncrementRevision", - "type": "Function", - "tags": [], - "label": "shouldIncrementRevision", - "description": [], - "signature": [ - "ShouldIncrementRevision", - " | undefined" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsIds", - "type": "Interface", - "tags": [], - "label": "BulkEditOptionsIds", - "description": [], - "signature": [ - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.BulkEditOptionsIds", - "text": "BulkEditOptionsIds" - }, - "" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsIds.ids", - "type": "Array", - "tags": [], - "label": "ids", - "description": [], - "signature": [ - "string[]" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsIds.operations", - "type": "Array", - "tags": [], - "label": "operations", - "description": [], - "signature": [ - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.BulkEditOperation", - "text": "BulkEditOperation" - }, - "[]" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsIds.paramsModifier", - "type": "Function", - "tags": [], - "label": "paramsModifier", - "description": [], - "signature": [ - "RuleParamsModifier", - " | undefined" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptionsIds.shouldIncrementRevision", - "type": "Function", - "tags": [], - "label": "shouldIncrementRevision", - "description": [], - "signature": [ - "ShouldIncrementRevision", - " | undefined" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "alerting", "id": "def-server.BulkOperationError", @@ -2737,7 +2551,7 @@ "label": "snoozeSchedule", "description": [], "signature": [ - "Readonly<{ id?: string | undefined; skipRecurrences?: string[] | undefined; } & { duration: number; rRule: Readonly<{ count?: number | undefined; interval?: number | undefined; freq?: 0 | 2 | 6 | 5 | 4 | 3 | 1 | undefined; until?: string | undefined; wkst?: \"MO\" | \"TU\" | \"WE\" | \"TH\" | \"FR\" | \"SA\" | \"SU\" | undefined; byweekday?: (string | number)[] | undefined; bymonth?: number[] | undefined; bysetpos?: number[] | undefined; } & { dtstart: string; tzid: string; bymonthday: number[]; byyearday: number[]; byweekno: number[]; byhour: number[]; byminute: number[]; bysecond: number[]; }>; }>[] | undefined" + "Readonly<{ id?: string | undefined; skipRecurrences?: string[] | undefined; } & { duration: number; rRule: Readonly<{ count?: number | undefined; interval?: number | undefined; freq?: 0 | 2 | 6 | 5 | 4 | 3 | 1 | undefined; until?: string | undefined; byweekday?: (string | number)[] | undefined; bymonth?: number[] | undefined; wkst?: \"MO\" | \"TU\" | \"WE\" | \"TH\" | \"FR\" | \"SA\" | \"SU\" | undefined; bysetpos?: number[] | undefined; } & { dtstart: string; tzid: string; bymonthday: number[]; byyearday: number[]; byweekno: number[]; byhour: number[]; byminute: number[]; bysecond: number[]; }>; }>[] | undefined" ], "path": "x-pack/plugins/alerting/server/application/rule/types/rule.ts", "deprecated": false, @@ -4321,57 +4135,9 @@ "label": "BulkEditOperation", "description": [], "signature": [ - "{ operation: \"delete\" | \"add\" | \"set\"; field: \"tags\"; value: string[]; } | { operation: \"add\" | \"set\"; field: \"actions\"; value: ", - "NormalizedAlertAction", - "[]; } | { operation: \"set\"; field: \"schedule\"; value: ", - { - "pluginId": "alerting", - "scope": "common", - "docId": "kibAlertingPluginApi", - "section": "def-common.IntervalSchedule", - "text": "IntervalSchedule" - }, - "; } | { operation: \"set\"; field: \"throttle\"; value: string | null | undefined; } | { operation: \"set\"; field: \"notifyWhen\"; value: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\" | null | undefined; } | { operation: \"set\"; field: \"snoozeSchedule\"; value: ", - { - "pluginId": "alerting", - "scope": "common", - "docId": "kibAlertingPluginApi", - "section": "def-common.RuleSnoozeSchedule", - "text": "RuleSnoozeSchedule" - }, - "; } | { operation: \"delete\"; field: \"snoozeSchedule\"; value?: string[] | undefined; } | { operation: \"set\"; field: \"apiKey\"; value?: undefined; }" - ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "alerting", - "id": "def-server.BulkEditOptions", - "type": "Type", - "tags": [], - "label": "BulkEditOptions", - "description": [], - "signature": [ - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.BulkEditOptionsFilter", - "text": "BulkEditOptionsFilter" - }, - " | ", - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.BulkEditOptionsIds", - "text": "BulkEditOptionsIds" - }, - "" + "Readonly<{} & { value: string[]; operation: \"delete\" | \"add\" | \"set\"; field: \"tags\"; }> | Readonly<{} & { value: Readonly<{ frequency?: Readonly<{} & { throttle: string | null; notifyWhen: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; summary: boolean; }> | undefined; uuid?: string | undefined; } & { id: string; params: Record; group: string; }>[]; operation: \"add\" | \"set\"; field: \"actions\"; }> | Readonly<{} & { value: Readonly<{} & { interval: string; }>; operation: \"set\"; field: \"schedule\"; }> | Readonly<{} & { value: string | null; operation: \"set\"; field: \"throttle\"; }> | Readonly<{} & { value: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; operation: \"set\"; field: \"notifyWhen\"; }> | Readonly<{} & { value: Readonly<{ id?: string | undefined; } & { duration: number; rRule: Readonly<{ count?: number | undefined; interval?: number | undefined; freq?: 0 | 2 | 3 | 1 | undefined; until?: string | undefined; byweekday?: string[] | undefined; bymonthday?: number[] | undefined; bymonth?: number[] | undefined; } & { dtstart: string; tzid: string; }>; }>; operation: \"set\"; field: \"snoozeSchedule\"; }> | Readonly<{ value?: string[] | undefined; } & { operation: \"delete\"; field: \"snoozeSchedule\"; }> | Readonly<{} & { operation: \"set\"; field: \"apiKey\"; }>" ], - "path": "x-pack/plugins/alerting/server/rules_client/methods/bulk_edit.ts", + "path": "x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -4774,38 +4540,10 @@ "text": "RuleTypeParams" }, ">(options: ", - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.BulkEditOptions", - "text": "BulkEditOptions" - }, - ") => Promise<{ rules: ", - { - "pluginId": "alerting", - "scope": "common", - "docId": "kibAlertingPluginApi", - "section": "def-common.SanitizedRule", - "text": "SanitizedRule" - }, - "[]; skipped: ", - { - "pluginId": "alerting", - "scope": "common", - "docId": "kibAlertingPluginApi", - "section": "def-common.BulkActionSkipResult", - "text": "BulkActionSkipResult" - }, - "[]; errors: ", - { - "pluginId": "alerting", - "scope": "server", - "docId": "kibAlertingPluginApi", - "section": "def-server.BulkOperationError", - "text": "BulkOperationError" - }, - "[]; total: number; }>; bulkEnableRules: (options: ", + "BulkEditOptions", + ") => Promise<", + "BulkEditResult", + ">; bulkEnableRules: (options: ", "BulkOptions", ") => Promise<{ errors: ", { @@ -10477,7 +10215,7 @@ "signature": [ "Omit<", "Options", - ", \"dtstart\" | \"until\" | \"wkst\" | \"byweekday\"> & { dtstart: string; byweekday?: (string | number)[] | undefined; wkst?: ", + ", \"dtstart\" | \"until\" | \"byweekday\" | \"wkst\"> & { dtstart: string; byweekday?: (string | number)[] | undefined; wkst?: ", { "pluginId": "@kbn/rrule", "scope": "common", diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 8c2e3125e78855f..814213ba42d8d12 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 795 | 1 | 765 | 48 | +| 784 | 1 | 754 | 47 | ## Client diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 86ca9300c8707ab..8a6a35c85b2ceb0 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index d9d501df2425ea1..63066ed4211119c 100644 --- a/api_docs/asset_manager.mdx +++ b/api_docs/asset_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetManager title: "assetManager" image: https://source.unsplash.com/400x175/?github description: API docs for the assetManager plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 451f7d6d33f80e0..d2862acf5a3223a 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index aa0358f7e421015..83c1d5e7375fa53 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index 9ecc55af7492ffc..0cb073d3302405e 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.devdocs.json b/api_docs/cases.devdocs.json index c66153d2d2fb262..d7975a35756fcbc 100644 --- a/api_docs/cases.devdocs.json +++ b/api_docs/cases.devdocs.json @@ -70,7 +70,7 @@ "section": "def-public.ICasesDeepLinkId", "text": "ICasesDeepLinkId" }, - ", Partial>> | undefined; }) => { id: \"cases\"; path: string; deepLinks: ({ id: \"cases_create\"; path: string; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; deepLinks?: T[\"deepLinks\"] | undefined; } | { id: \"cases_configure\"; path: string; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; deepLinks?: T[\"deepLinks\"] | undefined; })[]; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; }" + ", Partial>> | undefined; }) => { id: \"cases\"; path: string; deepLinks: ({ id: \"cases_create\"; path: string; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; deepLinks?: T[\"deepLinks\"] | undefined; } | { id: \"cases_configure\"; path: string; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; deepLinks?: T[\"deepLinks\"] | undefined; })[]; title: any; keywords?: T[\"keywords\"] | undefined; navLinkStatus?: T[\"navLinkStatus\"] | undefined; searchable?: T[\"searchable\"] | undefined; category?: T[\"category\"] | undefined; order?: T[\"order\"] | undefined; tooltip?: T[\"tooltip\"] | undefined; euiIconType?: T[\"euiIconType\"] | undefined; icon?: T[\"icon\"] | undefined; }" ], "path": "x-pack/plugins/cases/public/common/navigation/deep_links.ts", "deprecated": false, @@ -486,7 +486,7 @@ "section": "def-common.CaseSeverity", "text": "CaseSeverity" }, - " | undefined; assignees?: string | string[] | undefined; reporters?: string | string[] | undefined; defaultSearchOperator?: \"AND\" | \"OR\" | undefined; from?: string | undefined; search?: string | undefined; searchFields?: \"description\" | \"title\" | \"closed_by.username\" | \"closed_by.full_name\" | \"closed_by.email\" | \"closed_by.profile_uid\" | \"created_by.username\" | \"created_by.full_name\" | \"created_by.email\" | \"created_by.profile_uid\" | \"connector.name\" | \"connector.type\" | \"external_service.pushed_by.username\" | \"external_service.pushed_by.full_name\" | \"external_service.pushed_by.email\" | \"external_service.pushed_by.profile_uid\" | \"external_service.connector_name\" | \"external_service.external_id\" | \"external_service.external_title\" | \"external_service.external_url\" | \"title.keyword\" | \"updated_by.username\" | \"updated_by.full_name\" | \"updated_by.email\" | \"updated_by.profile_uid\" | (\"description\" | \"title\" | \"closed_by.username\" | \"closed_by.full_name\" | \"closed_by.email\" | \"closed_by.profile_uid\" | \"created_by.username\" | \"created_by.full_name\" | \"created_by.email\" | \"created_by.profile_uid\" | \"connector.name\" | \"connector.type\" | \"external_service.pushed_by.username\" | \"external_service.pushed_by.full_name\" | \"external_service.pushed_by.email\" | \"external_service.pushed_by.profile_uid\" | \"external_service.connector_name\" | \"external_service.external_id\" | \"external_service.external_title\" | \"external_service.external_url\" | \"title.keyword\" | \"updated_by.username\" | \"updated_by.full_name\" | \"updated_by.email\" | \"updated_by.profile_uid\")[] | undefined; rootSearchFields?: string[] | undefined; sortField?: string | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; to?: string | undefined; owner?: string | string[] | undefined; category?: string | string[] | undefined; } & Partial<", + " | undefined; assignees?: string | string[] | undefined; reporters?: string | string[] | undefined; defaultSearchOperator?: \"AND\" | \"OR\" | undefined; from?: string | undefined; search?: string | undefined; searchFields?: \"description\" | \"title\" | (\"description\" | \"title\")[] | undefined; sortField?: \"category\" | \"title\" | \"createdAt\" | \"updatedAt\" | \"status\" | \"severity\" | \"closedAt\" | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; to?: string | undefined; owner?: string | string[] | undefined; category?: string | string[] | undefined; } & Partial<", "Pagination", ">, signal?: AbortSignal | undefined) => Promise<", { diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 3fc3ec064c5b48f..21ee529e0f3c2cd 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 97418f8b31b1e35..d06236554db4853 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 2f981770cdf037d..99f4c5d9c6f47ca 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index 517cde284ab29d3..c4da9ddbce37685 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_chat_provider.mdx b/api_docs/cloud_chat_provider.mdx index 409ab5be424a335..8d35ac81834e431 100644 --- a/api_docs/cloud_chat_provider.mdx +++ b/api_docs/cloud_chat_provider.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChatProvider title: "cloudChatProvider" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChatProvider plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChatProvider'] --- import cloudChatProviderObj from './cloud_chat_provider.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index aa8af27faaadbf7..4e4dc5a3f6e9f4c 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.devdocs.json b/api_docs/cloud_defend.devdocs.json index 77489db1f3f8c42..fc3ac94a1e0fb54 100644 --- a/api_docs/cloud_defend.devdocs.json +++ b/api_docs/cloud_defend.devdocs.json @@ -799,7 +799,7 @@ "label": "SelectorCondition", "description": [], "signature": [ - "\"containerImageFullName\" | \"containerImageName\" | \"containerImageTag\" | \"kubernetesClusterId\" | \"kubernetesClusterName\" | \"kubernetesNamespace\" | \"kubernetesPodLabel\" | \"kubernetesPodName\" | \"targetFilePath\" | \"ignoreVolumeFiles\" | \"ignoreVolumeMounts\" | \"operation\" | \"processExecutable\" | \"processName\" | \"sessionLeaderInteractive\"" + "\"operation\" | \"containerImageFullName\" | \"containerImageName\" | \"containerImageTag\" | \"kubernetesClusterId\" | \"kubernetesClusterName\" | \"kubernetesNamespace\" | \"kubernetesPodLabel\" | \"kubernetesPodName\" | \"targetFilePath\" | \"ignoreVolumeFiles\" | \"ignoreVolumeMounts\" | \"processExecutable\" | \"processName\" | \"sessionLeaderInteractive\"" ], "path": "x-pack/plugins/cloud_defend/common/v1.ts", "deprecated": false, diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index 09947d662e000bc..7069c066ef4d1e3 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 99e80c5a18eebd8..dd9d118c73927be 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 91914937b66968f..2fd5276b580400a 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index dafec87bb83349f..73ceda8f05d67f0 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 431ca10b8325063..25922a2d902c808 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index bb63d34537ff566..289f80d9d6e76ee 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 5bd5eba882521a8..56cd9401d41d508 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 3d96815cf9ddd82..6ba76c6edfd6686 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 50764401c8008ed..b0da2f5d6bc7ce3 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 343f0f187b93200..0b5a25186659925 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 8d44a06320c398d..db40c196a7815ce 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index 1b61dd43131605f..b4c44781b50fa5d 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -3121,11 +3121,11 @@ "section": "def-common.SavedObjectsPitParams", "text": "SavedObjectsPitParams" }, - " | undefined; defaultSearchOperator?: \"AND\" | \"OR\" | undefined; searchFields?: string[] | undefined; rootSearchFields?: string[] | undefined; sortOrder?: ", + " | undefined; defaultSearchOperator?: \"AND\" | \"OR\" | undefined; searchFields?: string[] | undefined; sortOrder?: ", "SortOrder", " | undefined; searchAfter?: ", "SortResults", - " | undefined; hasReference?: ", + " | undefined; rootSearchFields?: string[] | undefined; hasReference?: ", { "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 1996434aace9fbf..aec5ad8ed96f142 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index ac761b8e8f6151e..a98ff5cb434c428 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 837fd82c62468c5..3861b8fdb5da8b7 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index cff2990395d2a9a..e0cafbaff4fd4b8 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 141aea0d162ec1f..135e38c86baa7f5 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 8e7803cc99057c9..f3403ed2472e4e4 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 38ea388d075da38..9f0050fdd5ed66d 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -184,7 +184,6 @@ Safe to remove. | | expressions | | | expressions | | | expressions | -| | fleet | | | kibanaReact | | | kibanaReact | | | licensing | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 9f9232df1900891..7aa14364008f88e 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 33bfd8a2f4176e5..98bbc8853dd43b0 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 738dbceb6f3a43e..8e195456848cdef 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.devdocs.json b/api_docs/discover.devdocs.json index 152ac0c9a0f1def..4d259397fc193ad 100644 --- a/api_docs/discover.devdocs.json +++ b/api_docs/discover.devdocs.json @@ -24,6 +24,74 @@ } ], "interfaces": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverProfileOptions", + "type": "Interface", + "tags": [], + "label": "DiscoverProfileOptions", + "description": [], + "path": "src/plugins/discover/public/customizations/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverProfileOptions.customize", + "type": "Function", + "tags": [], + "label": "customize", + "description": [], + "signature": [ + "(options: ", + "CustomizationCallbackContext", + ") => void | (() => void) | Promise void)>" + ], + "path": "src/plugins/discover/public/customizations/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.DiscoverProfileOptions.customize.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "CustomizationCallbackContext" + ], + "path": "src/plugins/discover/public/customizations/types.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverProfileOptions.deepLinks", + "type": "Array", + "tags": [], + "label": "deepLinks", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-application-browser", + "scope": "common", + "docId": "kibKbnCoreApplicationBrowserPluginApi", + "section": "def-common.AppDeepLink", + "text": "AppDeepLink" + }, + "[] | undefined" + ], + "path": "src/plugins/discover/public/customizations/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "discover", "id": "def-public.DiscoverStateContainer", @@ -491,6 +559,78 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverProfileId", + "type": "Type", + "tags": [], + "label": "DiscoverProfileId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/discover/public/customizations/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "discover", + "id": "def-public.RegisterCustomizationProfile", + "type": "Type", + "tags": [], + "label": "RegisterCustomizationProfile", + "description": [], + "signature": [ + "(id: string, options: ", + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.DiscoverProfileOptions", + "text": "DiscoverProfileOptions" + }, + ") => void" + ], + "path": "src/plugins/discover/public/customizations/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "discover", + "id": "def-public.RegisterCustomizationProfile.$1", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "src/plugins/discover/public/customizations/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.RegisterCustomizationProfile.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + { + "pluginId": "discover", + "scope": "public", + "docId": "kibDiscoverPluginApi", + "section": "def-public.DiscoverProfileOptions", + "text": "DiscoverProfileOptions" + } + ], + "path": "src/plugins/discover/public/customizations/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "discover", "id": "def-public.SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER_ID", @@ -615,64 +755,59 @@ }, { "parentPluginId": "discover", - "id": "def-public.DiscoverStart.customize", + "id": "def-public.DiscoverStart.registerCustomizationProfile", "type": "Function", "tags": [], - "label": "customize", + "label": "registerCustomizationProfile", "description": [], "signature": [ - "(profileName: string, callback: ", + "(id: string, options: ", { "pluginId": "discover", "scope": "public", "docId": "kibDiscoverPluginApi", - "section": "def-public.CustomizationCallback", - "text": "CustomizationCallback" + "section": "def-public.DiscoverProfileOptions", + "text": "DiscoverProfileOptions" }, ") => void" ], "path": "src/plugins/discover/public/plugin.tsx", "deprecated": false, "trackAdoption": false, + "returnComment": [], "children": [ { "parentPluginId": "discover", - "id": "def-public.DiscoverStart.customize.$1", + "id": "def-public.DiscoverStart.registerCustomizationProfile.$1", "type": "string", "tags": [], - "label": "profileName", + "label": "id", "description": [], - "signature": [ - "string" - ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/customizations/types.ts", "deprecated": false, - "trackAdoption": false, - "isRequired": true + "trackAdoption": false }, { "parentPluginId": "discover", - "id": "def-public.DiscoverStart.customize.$2", - "type": "Function", + "id": "def-public.DiscoverStart.registerCustomizationProfile.$2", + "type": "Object", "tags": [], - "label": "callback", + "label": "options", "description": [], "signature": [ { "pluginId": "discover", "scope": "public", "docId": "kibDiscoverPluginApi", - "section": "def-public.CustomizationCallback", - "text": "CustomizationCallback" + "section": "def-public.DiscoverProfileOptions", + "text": "DiscoverProfileOptions" } ], - "path": "src/plugins/discover/public/plugin.tsx", + "path": "src/plugins/discover/public/customizations/types.ts", "deprecated": false, - "trackAdoption": false, - "isRequired": true + "trackAdoption": false } - ], - "returnComment": [] + ] } ], "lifecycle": "start", diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 64c8cd748110d32..8d2cc98e4a88ca7 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 97 | 0 | 71 | 14 | +| 105 | 0 | 79 | 14 | ## Client diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index d60a57e9722c9b2..90fff3f16287733 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 84475267581859a..c93e982cb6832bd 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 5acc88dc59aab00..592f551d3ca2f6f 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 0412623c4a93f90..c973e87e3b0e7c9 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 2f558fc52d0bfe6..5094563edf696d5 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 16ec85e0318cbea..af0f7e1c3903593 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 980a387be95dfeb..a5ca53c5d0189d9 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 73bbec743d57ef1..934a7e2309fc58c 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index c022d40d9ea43df..dce8508554ef424 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 4a3add6e01000c5..504e7a9aee5dea3 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index cc43ea1a61146d3..a5c2c4fbfb5ad91 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 2d54c99194d8639..631c775338e3443 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 589ffe8c7b85c19..b912b7da77162ff 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index a4bd3c4933ce90f..c758aa1142bfdfd 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 913858ae57e1bf8..e29f7e68a40998e 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index a8e1f1f327aac3c..f1bfd4f3130ba5a 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 675f05388a1a5a2..cd27d2621503008 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index a65a9a8503d3efe..aec273c13f524f4 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index fef8a16f3bb93d3..7acdd2d8a8b24ab 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index af09e4054950f47..9601a85ef617e1d 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index ed365ad68952e09..92de9fec7759cc4 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 26b51db8c893ce3..4f6635fc03a92d7 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 4f482e4f89f205e..dea1d4ba9e244f6 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 9f4a52775fc68a1..f8115a00f4be066 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 19a68028b04611a..4889045ee5b0b57 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.devdocs.json b/api_docs/field_formats.devdocs.json index d4f8c33a70b9ef0..066b2d29c4761f4 100644 --- a/api_docs/field_formats.devdocs.json +++ b/api_docs/field_formats.devdocs.json @@ -5534,6 +5534,36 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "fieldFormats", + "id": "def-common.DURATION_INPUT_FORMATS", + "type": "Array", + "tags": [], + "label": "DURATION_INPUT_FORMATS", + "description": [], + "signature": [ + "{ text: any; kind: string; }[]" + ], + "path": "src/plugins/field_formats/common/constants/duration_formats.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "fieldFormats", + "id": "def-common.DURATION_OUTPUT_FORMATS", + "type": "Array", + "tags": [], + "label": "DURATION_OUTPUT_FORMATS", + "description": [], + "signature": [ + "({ text: any; method: string; shortText?: undefined; } | { text: any; shortText: any; method: string; })[]" + ], + "path": "src/plugins/field_formats/common/constants/duration_formats.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "fieldFormats", "id": "def-common.FieldFormatConfig", @@ -6614,6 +6644,36 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "fieldFormats", + "id": "def-common.DEFAULT_DURATION_INPUT_FORMAT", + "type": "Object", + "tags": [], + "label": "DEFAULT_DURATION_INPUT_FORMAT", + "description": [], + "signature": [ + "{ text: any; kind: string; }" + ], + "path": "src/plugins/field_formats/common/constants/duration_formats.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "fieldFormats", + "id": "def-common.DEFAULT_DURATION_OUTPUT_FORMAT", + "type": "Object", + "tags": [], + "label": "DEFAULT_DURATION_OUTPUT_FORMAT", + "description": [], + "signature": [ + "{ text: any; method: string; }" + ], + "path": "src/plugins/field_formats/common/constants/duration_formats.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "fieldFormats", "id": "def-common.FORMATS_UI_SETTINGS", diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 40783989b462f33..e3d32135949db10 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 288 | 26 | 249 | 3 | +| 292 | 26 | 253 | 3 | ## Client diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index a32cb8088f74b89..7bea0d1f5631a5e 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 7dd92a6ceac8f8c..4079755e782d7ab 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index faec2f609c3f8d8..17450218cccd9fd 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index ee84d6deead3a73..325cf806cd27883 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -20654,9 +20654,7 @@ "parentPluginId": "fleet", "id": "def-common.ListWithKuery", "type": "Interface", - "tags": [ - "deprecated" - ], + "tags": [], "label": "ListWithKuery", "description": [], "signature": [ @@ -20677,9 +20675,8 @@ } ], "path": "x-pack/plugins/fleet/common/types/rest_spec/common.ts", - "deprecated": true, + "deprecated": false, "trackAdoption": false, - "references": [], "children": [ { "parentPluginId": "fleet", @@ -24224,6 +24221,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-common.FLEET_ENROLLMENT_API_PREFIX", + "type": "string", + "tags": [], + "label": "FLEET_ENROLLMENT_API_PREFIX", + "description": [], + "signature": [ + "\"fleet-enrollment-api-keys\"" + ], + "path": "x-pack/plugins/fleet/common/constants/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-common.FLEET_KUBERNETES_PACKAGE", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 7e418461e80fff5..53db65c1636f1a4 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1182 | 3 | 1066 | 40 | +| 1183 | 3 | 1067 | 40 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 7949d49a5f9afbe..76c24bd3a7782ba 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index d606445acda196c..fd8f627e7adf543 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 768929ebc71cb1d..0e167c6cecfc517 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 7a77f5003154fe1..4a55f4482950515 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 177500b95c2205e..5a2f3285805ea4a 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 99ef501f27afce9..4bd841c7ef17b0c 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index f6287d32f3f0f39..82592787c808647 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 3d8cb6f02a71a7f..83bdbdfd6a39318 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index df917b1b0cfcffc..d1d0a39d7115559 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 222a07588f4db5a..d20714010507f01 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 8a3333614b6ef2d..ba6531a1001cad6 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 422445121250a77..df9e97256e3d774 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 52cf43b1ae491af..3f9796c9cf7d084 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 3a1ba2203bf26f8..2f19ea35a0d007c 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index d4b1105b4d77d15..3cba26ec0dcfa30 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index f16c472439e3e25..804eb4606ba3900 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index d5cec25b58f1559..c2402dfa090dfad 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 8bc637e69fffc15..57a58498176de97 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index a41b2d2177c2df5..f8ff06ca69983ec 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 6e7d932ca330f69..c19a67097741cfd 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 70793ab646e9472..710372c57c4167f 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index 5e10bfcf1a73ca8..bd3819e110fdf4d 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index c09ab2c0e8c8ef4..e282a9244ac3efc 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 77f8b1edd7b2a41..f4d712b73fdb1f5 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 973c9fe6f3ab493..a76a3feaa546bef 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 061092d33c8bd78..21f3e7ec77e4dc0 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index bc26c5b37c8a941..dc06b9442c90c30 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index cbf19ca05335228..7e4331f65f653ea 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index b50f54ae3a990c7..0cd1ac5b87cc9bd 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index 7272389786dcf24..36cedd9869d5acb 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index d81652f3fa39e50..ca86b16c5d09b08 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 4d255f01a549022..b85ba8d9a2ccec8 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index 74604cc561d35c1..ffc1a3bd95e751b 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 4ba1c89c5e8b254..fe9980d90db447f 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 7d0578f06ebd6d6..01dab9b1e695f8b 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index 335a47543144d0d..d5eb796a42a0fee 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mocks.mdx b/api_docs/kbn_code_editor_mocks.mdx index bfc480bcfca3d0b..6bd479f1e6b4e07 100644 --- a/api_docs/kbn_code_editor_mocks.mdx +++ b/api_docs/kbn_code_editor_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mocks title: "@kbn/code-editor-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mocks'] --- import kbnCodeEditorMocksObj from './kbn_code_editor_mocks.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 47482c822d82b15..c6553274b25a2b4 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 5d99cd7f045adf5..af12011733c9b14 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 526ec1cea404ef1..7d18b57fee5a781 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 5133eaf9a6845f4..bd4f9dd4894dbe4 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 616332a5d8b1236..4daaa199b7c2182 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index e87d120aaae42a2..0142304beba2cd0 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index a8c5af21240b91d..f933247d4c9e46f 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index 16896670faca362..10bb54573769e60 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index 44895f72e439d32..16a8f6811924a05 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 4e74790ed5d97b0..b16d11ed8a92dbb 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index e1947a0c58e4cca..122a916c09644eb 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 9e32e28afd06b9f..af3f4e23d729121 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 31b7d3b48edcab9..7e9209391600183 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 8c9136dd4cdf4f5..a6f3b9bde2c5ae9 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index c77371d96aec9ea..d61c7d20547af8b 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.devdocs.json b/api_docs/kbn_core_application_browser.devdocs.json index 662fd133880ed80..1882894950b1b39 100644 --- a/api_docs/kbn_core_application_browser.devdocs.json +++ b/api_docs/kbn_core_application_browser.devdocs.json @@ -1777,7 +1777,15 @@ "section": "def-common.AppNavLinkStatus", "text": "AppNavLinkStatus" }, - " | undefined; searchable?: boolean | undefined; } & ", + " | undefined; searchable?: boolean | undefined; category?: ", + { + "pluginId": "@kbn/core-application-common", + "scope": "common", + "docId": "kibKbnCoreApplicationCommonPluginApi", + "section": "def-common.AppCategory", + "text": "AppCategory" + }, + " | undefined; } & ", { "pluginId": "@kbn/core-application-browser", "scope": "common", diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 673134a58cc467d..0374b2c1f1aa457 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index d4bf4adf8a1ed57..18cf0d771c6ad86 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 47c9867e3d1a633..545dfe5c4a586a5 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 39027dc51ffe636..527734039a05119 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index a8288c3940bea65..81683f4ac25ef28 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index bd3cb06e6f273a5..03adef72907cd01 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index d6b9f25679e906b..0adcd136c326628 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 5196048f57d0d09..dbcc023e85cc18f 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index f012cd09f90b8f2..ae4d6a0623b9ed2 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index a7b682fc33f76e0..8f2e82c11c54e5c 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index ed2e10213dbf94c..160ddfb8938e2d1 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 7153e74b8529ba0..4c03359b8ebc29a 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index d22463238fdefff..cf991a63e09b42a 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 518e3324f6fd5fb..6c2da802fe21a17 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index 56cd648966b6998..168fb812354ab61 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 5c96c0879691bb4..026729e31e79de5 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index 928c2bb1bf7d3f8..8c051b77f04b7c8 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index e9685a409f34132..8ac5e13cbdb585a 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index 8afc006a6250c8b..240df5ad686ccc0 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index d4cb231964b6057..3fb740938d13653 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 762fc9a0f61a06e..d3339d281cbca29 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index d247bb210c013ee..1dcf1880d54ce83 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 4eb20cd2cfe5b44..f10d139205af303 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index bd7ff24467bb762..9998a2483f61c37 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index 7209cc81f330ee4..8e2489e9d26133a 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index 7ba6e00825e4fd8..a612e2b09900f20 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 442459234ce0704..b32eb354ea748e9 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 1fcf675347e7f20..f120755e700607f 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 9195f243e79f784..27a45cad1057542 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 66cb11863cbd25c..17d6952016db942 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 15e2e5600c5e765..1817cfb8c76f0a7 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index aaf847ed15a788c..d1e1e67bef7a3d3 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 793de003dce573c..b7e28a36c8f1a97 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 8b4dd42a5117344..5a8d317376efbfc 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 8f47c3a508fe5b4..a6014fd24a5dbea 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index f371af9591a8a47..2fdfdfbb56f20d9 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 386120ac648c80f..9024c77a7a394e8 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index 971339e709e7dc0..21ac86a9435f57a 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 2dcdfbaa057d877..bdfed140b7f032b 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 1f18ac4128e48eb..1efade95ce97861 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 232bf10090358d5..e27b488d0cf92a5 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 11568e4d2b4c27c..8d626a2c44ae500 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index 79adadc2266e48a..6256fd6b00f3487 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index acaa681b1d3b295..1e7ad4a542eceda 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 6a2f27fdc60f075..a64e2b9ffae010e 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 872f57fe085025c..17625336a73b2b2 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 4da7de75fc7db1e..f9f66121a41b68b 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 2fdfc79cd21d0a4..92a485b3bab081c 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 1a6a207e5967d9c..dc8d473abedb816 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 7d9b9843d63c764..afc629954bb9e16 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 4af935717eb124f..5a8b5ecec85fe6f 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 934659604f45413..a1365c26e95a39f 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 843c9d557d115c2..bd1673ce430427d 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index 9a3153e7490239f..763bdd41ccdb0cf 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index ea5ded39f3fec5e..07530ed9dfd38a9 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 08d9c0f2e074b7a..db45ead3a1bdd5c 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 9cab3ca810063af..bb1e18af168b721 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index e4710571602e757..b5b46fe9558a02c 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index 21ec4edea150eff..264e3bec80c9c11 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index 2d3e3e2016f4262..1a5f2d99d1a40f9 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 3ab397177665846..701980bceb9652e 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 433c7d3916244ac..a8509fad61ec160 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 712d2b3121c53cb..4db8571f361290f 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.devdocs.json b/api_docs/kbn_core_http_server.devdocs.json index e0de3c7a3ff0889..bfea95fc28b2c8c 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -6319,7 +6319,7 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/create/create_rule_route.ts" + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.ts" }, { "plugin": "alerting", @@ -6359,15 +6359,15 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/snooze_rule.ts" + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/unsnooze_rule.ts" + "path": "x-pack/plugins/alerting/server/routes/snooze_rule.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/bulk_edit_rules.ts" + "path": "x-pack/plugins/alerting/server/routes/unsnooze_rule.ts" }, { "plugin": "alerting", @@ -7561,22 +7561,6 @@ "plugin": "actions", "path": "x-pack/plugins/actions/server/routes/get_oauth_access_token.test.ts" }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/bulk_edit_rules.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/bulk_edit_rules.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/bulk_edit_rules.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/bulk_edit_rules.test.ts" - }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/clone_rule.test.ts" @@ -7961,34 +7945,6 @@ "plugin": "remoteClusters", "path": "x-pack/plugins/remote_clusters/server/routes/api/add_route.test.ts" }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/create/create_rule_route.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/rule/create/create_rule_route.test.ts" - }, { "plugin": "crossClusterReplication", "path": "x-pack/plugins/cross_cluster_replication/server/routes/api/auto_follow_pattern/register_create_route.test.ts" @@ -8029,6 +7985,50 @@ "plugin": "spaces", "path": "x-pack/plugins/spaces/server/routes/api/external/update_objects_spaces.test.ts" }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_edit/bulk_edit_rules_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/create/create_rule_route.test.ts" + }, { "plugin": "home", "path": "src/plugins/home/server/plugin.test.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 925af45a6f16dfd..dee0c197b97603d 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 862ba1be9c13181..3f5935720e4e115 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index f3f7ec6bca191eb..d590ef97f31468f 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index df3a075fcfc2990..61f1dce7ed20905 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 8454ad662a246b2..1d5da759f274acd 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index b0e32bef612b071..3429c4f096e4762 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index c902864ed3395b1..16adf76ed1c98f5 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index d37b3d3269051ca..9bfa4bfd73259d6 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 6538b19bd7d5ea0..5b908a45c0227c0 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 2f000f37789eca2..7a05be32c4db469 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index aba5da86076de01..1d3ea26d5201e2e 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index a9aa2d998638672..94a0c1e2db815f6 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index ff13480f58fe559..08d311894967ed9 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index ec0aa477669cca1..5905f57c24b6b17 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index 54507fa0b41b35a..d4db2fb2779a2a6 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 291714ce0306bb1..6650efe5ccdecd8 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index 8000a0cb185ad79..3aeaf8da670076e 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index a251a63d4f39103..15b9ab447ffe7e4 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 99ad310c9e6eda1..942c6bc64ebde76 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index ec7cb6718a3e6c5..ec049a41394fe0d 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index a76c9ca5d77f1e8..a7e03688bbaa7d9 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 168abc581731d5c..51c2fc4563e2c62 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 8541b76234a3bae..c02093fe7b4ab3a 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index 329058dec402303..dfe19d505f12280 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index c4680b05b834a23..18b346c1b57f3e9 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 0db445536b4267a..b08016de4b2a06b 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 432d7af78412e92..a8cd0dcee179b10 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 9221269456bf4d4..c96fc82d4b89995 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 24583c8b89996f8..8ff8fa06607a712 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 24dd1efbd6c6c06..e8460565c22d40e 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index bc6ef00f60318ce..30cfb53e02b0083 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index bcf5435a192ca7c..110549144481594 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index fc014bc71e72127..4092ba097d2bb04 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index 1ba83503bded443..4917810b75e5906 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index daded7606447859..1e062986db2fcca 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index 25594e6959d67e7..197ed745642c617 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index b1d285d342cdf36..1a93d4aafebf568 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 092b98e447d4247..f9c3b1e84dd848a 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 1cc4b7be42a2757..ef2c5d034599542 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 4afcbeec9148c92..792cb9a637c5c7f 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 770a6ab32a9f126..6b1f7fd37b69ebf 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index 8310b6c022388f9..20cc17a311eb4a0 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index c13a33dbe17baf2..dfe877ff38a983f 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index b4920fe30722eba..3db82c0b14f9fb3 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index a115ae3a3be60c5..180b17380daa1b8 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 75c7829fdb177b8..5313d490d7b2978 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.devdocs.json b/api_docs/kbn_core_saved_objects_api_server.devdocs.json index 31fbb9fb8cb39e4..16928f702204e6c 100644 --- a/api_docs/kbn_core_saved_objects_api_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_server.devdocs.json @@ -2720,11 +2720,11 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/rules_client/common/inject_references.ts" + "path": "x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/rules_client/common/inject_references.ts" + "path": "x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts" }, { "plugin": "alerting", @@ -2740,11 +2740,11 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts" + "path": "x-pack/plugins/alerting/server/rules_client/common/inject_references.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts" + "path": "x-pack/plugins/alerting/server/rules_client/common/inject_references.ts" }, { "plugin": "alerting", @@ -8213,9 +8213,9 @@ "signature": [ "{ type: string | string[]; search?: string | undefined; filter?: any; aggs?: Record | undefined; namespaces?: string[] | undefined; perPage?: number | undefined; fields?: string[] | undefined; sortField?: string | undefined; preference?: string | undefined; defaultSearchOperator?: \"AND\" | \"OR\" | undefined; searchFields?: string[] | undefined; rootSearchFields?: string[] | undefined; sortOrder?: ", + "> | undefined; namespaces?: string[] | undefined; perPage?: number | undefined; fields?: string[] | undefined; sortField?: string | undefined; preference?: string | undefined; defaultSearchOperator?: \"AND\" | \"OR\" | undefined; searchFields?: string[] | undefined; sortOrder?: ", "SortOrder", - " | undefined; hasReference?: ", + " | undefined; rootSearchFields?: string[] | undefined; hasReference?: ", { "pluginId": "@kbn/core-saved-objects-api-server", "scope": "common", diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 1200b03ff4d39e6..2b95dc8082bc22a 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 1de7325f058fcf8..6ad999a7d649bf5 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 311236e406346ab..00241eb5fd39833 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 7aa35326b57ec86..9132f7f5ec0a429 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 2ac196984e3a902..de93f0579e0992d 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 0ff1289a9d9dfb5..e6c37906a631a50 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 5a76e19599642a8..18086270c9e4993 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index ff1452db113e503..d271f676e6e1d6f 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index 59b6972f2d810c5..e7bcdf73cc06a54 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 674311fd10a8319..367d5ec6f6623ba 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index 42dd85d76ef4bd2..b9cc0b34bdd0e3b 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index c9086e3b1aee9fe..784ebfd38b329ff 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.devdocs.json b/api_docs/kbn_core_saved_objects_server.devdocs.json index c8938d2d3114486..706b7e0a90e5183 100644 --- a/api_docs/kbn_core_saved_objects_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_server.devdocs.json @@ -6185,11 +6185,11 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/rules_client/common/inject_references.ts" + "path": "x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/rules_client/common/inject_references.ts" + "path": "x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts" }, { "plugin": "alerting", @@ -6205,11 +6205,11 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts" + "path": "x-pack/plugins/alerting/server/rules_client/common/inject_references.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/data/rule/types/rule_attributes.ts" + "path": "x-pack/plugins/alerting/server/rules_client/common/inject_references.ts" }, { "plugin": "alerting", diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 5075efffecaa01d..163b412768ee8e3 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index d034b7c1aa33d43..ba24948eb708ed7 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index b06f1f14185e100..5c8d14a21955162 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 7d3af63ef1cf395..3381e84f152a0d8 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 08c3e35a0111888..5cf45c5f334b778 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index 741b39cfe85c3a2..33c9050a6f0fec3 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 22e45ccd1b0beea..decce22bb230921 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 6c3e9ab7ab6ca5c..0558bc97f1681ab 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 375c05d88270815..05a7e9530189f6f 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 1844b13afe91783..df016f324e14fe6 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index ff1117dba0b4263..d0f199ee59552de 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 60da99c5cc2a165..4c16264b94ee658 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 6a3ef6718a504a8..e77f1529b422e5a 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index 505e6abe4b8f9b1..fa4132098cc2bc5 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index e4f09b708485610..187071c3f052e8d 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index d148bee54a35869..ff390281a07677e 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 3e112d9c541fbeb..ffed699e165d062 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index e077409424ce68d..d1a59928505aa6b 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 2b7d56fcb5a820a..1b19d54096ac27a 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index a1cbebbbc8164ef..a74c28410b2db6f 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 573c115c955d746..9bb2d6407132023 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index deb2a55c01a7d4f..11f25b3d7e1d601 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 27a0ae49f655a25..50ead83c4331909 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index 862f6ce5894843d..2b3513ab873d13c 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 7a6cfcd02c2b81f..1b433abb110e967 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index ee9a12e4c6e7b29..df6456e1d53e519 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 6bbdebdad51dd70..50e5e07dcd5a770 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index 89c34a0d12e6119..857b76b0ceb755a 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_internal.mdx b/api_docs/kbn_core_user_settings_server_internal.mdx index ea4d32e7dd654d3..04881cb69ff27b9 100644 --- a/api_docs/kbn_core_user_settings_server_internal.mdx +++ b/api_docs/kbn_core_user_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-internal title: "@kbn/core-user-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-internal plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-internal'] --- import kbnCoreUserSettingsServerInternalObj from './kbn_core_user_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index 0c0648aed5f885e..5a5235ca50b6717 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 50f290712bb47b9..7e18a4535eb4e9c 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 4320150150645a9..6b7437ae11daa0c 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 554ad6d3f78d3a2..12249b11fe15ce8 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 6ebdefe566fa5cc..230da3d6bcd6117 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 89c1af63db870d5..d93d484303efd2f 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index a3ed9f7a36846c5..1a6164d80820839 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index 1aa7f37ac7bd798..fefc3780a69418f 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index 89356fd2b5f6a1c..c533701f4d2f61e 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index c4cab9223d38678..db17cb42f22d743 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.devdocs.json b/api_docs/kbn_deeplinks_observability.devdocs.json index 51a50d02fa1b1fa..dbcbc0da8d1919c 100644 --- a/api_docs/kbn_deeplinks_observability.devdocs.json +++ b/api_docs/kbn_deeplinks_observability.devdocs.json @@ -52,7 +52,7 @@ "section": "def-common.AppId", "text": "AppId" }, - " | \"logs:settings\" | \"logs:stream\" | \"logs:log-categories\" | \"logs:anomalies\" | \"observability-overview:cases\" | \"observability-overview:rules\" | \"observability-overview:alerts\" | \"observability-overview:cases_create\" | \"observability-overview:cases_configure\" | \"observability-overview:slos\" | \"metrics:settings\" | \"metrics:inventory\" | \"metrics:metrics-explorer\" | \"metrics:metrics-hosts\" | \"apm:traces\" | \"apm:dependencies\" | \"apm:service-map\" | \"apm:settings\" | \"apm:services\" | \"apm:service-groups-list\" | \"apm:storage-explorer\"" + " | \"discover:log-explorer\" | \"logs:settings\" | \"logs:stream\" | \"logs:log-categories\" | \"logs:anomalies\" | \"observability-overview:cases\" | \"observability-overview:rules\" | \"observability-overview:alerts\" | \"observability-overview:cases_create\" | \"observability-overview:cases_configure\" | \"observability-overview:slos\" | \"metrics:settings\" | \"metrics:inventory\" | \"metrics:metrics-explorer\" | \"metrics:metrics-hosts\" | \"apm:traces\" | \"apm:dependencies\" | \"apm:service-map\" | \"apm:settings\" | \"apm:services\" | \"apm:service-groups-list\" | \"apm:storage-explorer\"" ], "path": "packages/deeplinks/observability/deep_links.ts", "deprecated": false, diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index c14a1aa913226ec..3d2540bbfa7731b 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index 580392c198db308..d55882c96634a6d 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index ec67b9b7b084f5b..8b56232b719df4e 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index bf8f2c878564544..4196d2376706618 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index f9b9cdc53c6a272..4b3aa89286d28b8 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index 36d515a2384102e..9441ed77ff8247c 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index f6dac5b99ce0fe0..e71ea0e5e9db3f9 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index ecdc362a9c24c86..2e83993d4c556b5 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index cb5184c1773cb98..7b053a31a8f1c43 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index a8fc0c2cca792f0..9a735dfe01f6ddc 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 83823d5d9f080ee..5964e9b5fefb2de 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 9f1453f69bebd38..8b67ec2a4f2cf65 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 223a3579adb6ee4..5cd1833c4d3c9e5 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index 5206e9a80847667..35f9dc33c83fe0b 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 017d7b167156500..fcdc006b92732fc 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index 84e11f57bd1b183..58ed67648361b3c 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 1b491c90aa120b6..4da00475ce45e6b 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index af6e5719aaeab57..c4c217f6e20ee47 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 63441d01696c487..9d99574fe0e56fd 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 06d8e6ddf1fea2e..10183fda444dec0 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index d5792a8fe7775de..301192aa95f8d83 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index c1e74accd142d09..a4039d8d7af8c8a 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index c01a05e9313386c..55fab7296a76c03 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 58b08a1ee77d586..94a9d2310534976 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index c38c4b07a180c60..1fe37b12194d863 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index 95dd3b25b665a22..f36f483531513e3 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.devdocs.json b/api_docs/kbn_expandable_flyout.devdocs.json index bff7c42b7371964..de3d777b065604d 100644 --- a/api_docs/kbn_expandable_flyout.devdocs.json +++ b/api_docs/kbn_expandable_flyout.devdocs.json @@ -184,24 +184,24 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, " | undefined; right?: ", { "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, " | undefined; preview?: ", { "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, " | undefined; }) => void" ], @@ -232,8 +232,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, " | undefined" ], @@ -253,8 +253,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, " | undefined" ], @@ -274,8 +274,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, " | undefined" ], @@ -303,8 +303,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, ") => void" ], @@ -324,8 +324,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" } ], "path": "packages/kbn-expandable-flyout/src/context.tsx", @@ -351,8 +351,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, ") => void" ], @@ -372,8 +372,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" } ], "path": "packages/kbn-expandable-flyout/src/context.tsx", @@ -399,8 +399,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" }, ") => void" ], @@ -420,8 +420,8 @@ "pluginId": "@kbn/expandable-flyout", "scope": "common", "docId": "kibKbnExpandableFlyoutPluginApi", - "section": "def-common.FlyoutPanel", - "text": "FlyoutPanel" + "section": "def-common.FlyoutPanelProps", + "text": "FlyoutPanelProps" } ], "path": "packages/kbn-expandable-flyout/src/context.tsx", @@ -588,10 +588,10 @@ }, { "parentPluginId": "@kbn/expandable-flyout", - "id": "def-common.FlyoutPanel", + "id": "def-common.FlyoutPanelProps", "type": "Interface", "tags": [], - "label": "FlyoutPanel", + "label": "FlyoutPanelProps", "description": [], "path": "packages/kbn-expandable-flyout/src/types.ts", "deprecated": false, @@ -599,7 +599,7 @@ "children": [ { "parentPluginId": "@kbn/expandable-flyout", - "id": "def-common.FlyoutPanel.id", + "id": "def-common.FlyoutPanelProps.id", "type": "string", "tags": [], "label": "id", @@ -612,7 +612,7 @@ }, { "parentPluginId": "@kbn/expandable-flyout", - "id": "def-common.FlyoutPanel.params", + "id": "def-common.FlyoutPanelProps.params", "type": "Object", "tags": [], "label": "params", @@ -628,7 +628,7 @@ }, { "parentPluginId": "@kbn/expandable-flyout", - "id": "def-common.FlyoutPanel.path", + "id": "def-common.FlyoutPanelProps.path", "type": "Array", "tags": [], "label": "path", @@ -644,7 +644,7 @@ }, { "parentPluginId": "@kbn/expandable-flyout", - "id": "def-common.FlyoutPanel.state", + "id": "def-common.FlyoutPanelProps.state", "type": "Object", "tags": [], "label": "state", diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index bbb8e3238ba260b..96a6c756988d301 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 41816ad613c5ffd..01809fb3fbbd82f 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index ed07b62d900b7a6..2d2be17d9845cca 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index d2da3fadf63db97..70887e0ced0e285 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index b2856531b8a76cc..1ff30da7dc991db 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index 25113039bbddcd3..a9c14b887d20d95 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index 35b5cebc9704e3d..5648d71ed13e99e 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_generate_csv_types.mdx b/api_docs/kbn_generate_csv_types.mdx index 8b029a35fcd8a1f..b2abf10ae734090 100644 --- a/api_docs/kbn_generate_csv_types.mdx +++ b/api_docs/kbn_generate_csv_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv-types title: "@kbn/generate-csv-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv-types'] --- import kbnGenerateCsvTypesObj from './kbn_generate_csv_types.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 1e45fe0ae1396de..e56aacd6d0527a7 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index d841fbc69f8d31a..ec517f431b6060c 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 34c8ceaa80f3b74..8f5e2ad5faf1d8e 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index f4cb554224891c3..bf1a360a20b00f9 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 016b164e2c21309..63c3bf3b580bfe6 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 675652182746500..84a9d8eb79711a8 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index a599ed90b39e925..bfd9be76b432aed 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 55be3a7bf153a05..074b3fa79b622a2 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 43343eaf6b11575..b1cf84aa41512f8 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index f22d939806a0fdc..bc5837d6b21ab60 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index d058a7b6a344f6c..854a288b6e52810 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 8651662103eb78d..f18a2ad311a7c08 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index d60ea406e5d5e19..0be75367d5e346f 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 92926ac1e64e960..da4019dcb61c89f 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index 279cccf564d0f0d..f84a3ac7ac7711a 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 450781e6d2de8ea..4269bd9e71e5917 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index 1ff7d20dd502a1e..f2cf653ff7162af 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 6917138f57f3a78..ac2c85c35be2bbf 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index 32d115174b67431..790f585b4ac638b 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 94cb51eecdb660a..2dcde8b341ddd99 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index 46216aabfbb5622..8917fc079b02838 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 09fd0a34a3a851a..8c60f5c93e06abc 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index f0fb457ebb2e666..111cff557ba185d 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index 9dc9b1bb25d1f68..f187e644662de6c 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index bcee95273cb6290..208e1d6d282dc70 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index bd01fb905bf426c..111c51eca18dde9 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index c3661be93c9b2de..f1650993f602b6c 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index 4054fe202edcd54..384d0caad02dca4 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index 355004bcb5a439d..972f4df235ccf7b 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 4c5d861ba11a617..8d8c1e736b6a10a 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index 04594325e222d6a..e798ef7e3863230 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index edc4a9229f23dd1..08d263734130dd5 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index d27b2b6664381b8..3241437c4a2a4ac 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index b6331b01f94193f..be815e8dba43816 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index f9aaa94a127c5db..be98571561f4c61 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index 37a6fa67fc0af0a..b68c3823a293d33 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index 74f61d0ec2e0cb3..49d867252d8a9cb 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index ec3c945fb65be73..e72a6e903103aeb 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 4827e881a189586..0a7557b62342af8 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index 1afd33f0bff852c..adf8fc8d12ec29f 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index e2e308b7b32fb88..7a5d89eefb986ad 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index f8d876f9822f7ed..3d5544147a92348 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index dc978619a0c2aae..76a30cc76a6ca73 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index f65f1ed13ca9435..f974b61fe9a2bb5 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 9c2c745ab3a6b8b..8178c6175a2b722 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index e01f819d5118f7b..318a6e683e1c66d 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index a708787c6a9f3c5..a25ca8978357742 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index 6b012306a44ce93..694b0a21e302c2a 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 484a424f656e3a5..17dc88492677c3d 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 42ad7b809a2fb2d..bd4e31d36e20d1c 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index 29214c854803be7..2fe2472615a5938 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 1b960fd5b429ce3..a114c07a2ca3f96 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 555978b1219aa83..35aa8a6bf4530f6 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 239aacbb159bf36..8bf90403d056b57 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 0699f01f31ff9a8..bbfe67f9b1f5be2 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index d0e9f49d3b663d3..0131d22c1fd34ee 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index ceebf1de2d45809..22745d35ab9ea2d 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 50e44778b928601..470b6859cbe0f32 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index 172f31ad45843ca..c9a2335974255d9 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index c40105eed3c2fe9..4cb34a12fa07a87 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 87d9210cc652d92..d6ecccf53f02b27 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 8bd74b0d9528279..32204e355b6bd96 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rrule.devdocs.json b/api_docs/kbn_rrule.devdocs.json index 849f4cc2f8ff788..a2359c9a4e56a21 100644 --- a/api_docs/kbn_rrule.devdocs.json +++ b/api_docs/kbn_rrule.devdocs.json @@ -245,7 +245,7 @@ "label": "ConstructorOptions", "description": [], "signature": [ - "Omit & { byweekday?: (string | number)[] | null | undefined; wkst?: number | \"MO\" | \"TU\" | \"WE\" | \"TH\" | \"FR\" | \"SA\" | \"SU\" | null | undefined; }" + "Omit & { byweekday?: (string | number)[] | null | undefined; wkst?: number | \"MO\" | \"TU\" | \"WE\" | \"TH\" | \"FR\" | \"SA\" | \"SU\" | null | undefined; }" ], "path": "packages/kbn-rrule/rrule.ts", "deprecated": false, diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index d51cf807f3d5e2c..10ac52ad6edb61c 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index aaa346f1947d871..93a2b0ff6dbd7b0 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index ecaa3aa381d5e17..112c155672699cb 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index 4a43ce7834efb9e..362e81d3b55845b 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index 3134f87f4277a10..e0c6c56ff9c7f05 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 71a56ad44186b18..07d5c06940fd26a 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index 8628b9249bc34e5..db1190923d0da89 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index c1afc18c019cae6..451a5f2bf7f4232 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index fa517d8e7021878..eda86e138f44386 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 845f99b4dfe3774..9e597377db20f07 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_grouping.mdx b/api_docs/kbn_securitysolution_grouping.mdx index 9eaf7fa671103d6..fc9f071bd929847 100644 --- a/api_docs/kbn_securitysolution_grouping.mdx +++ b/api_docs/kbn_securitysolution_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-grouping title: "@kbn/securitysolution-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-grouping plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-grouping'] --- import kbnSecuritysolutionGroupingObj from './kbn_securitysolution_grouping.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 5206d20c7499923..d799dbf789b5f8e 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 062cd1b77120eb3..326b20ed158f920 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 108d73572c086ca..eceeed07bbfcb5d 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 2f91a2397144aa0..2f12fcfc1e642e3 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index fa4c1af425971c9..2b3b132b2ffa44a 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 5648433675c5eb5..c4ed7d84d64cb66 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 8ad5da9a30f144d..5e22f25f73a6fa8 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index e84823d3b4f9f21..631fa41b83d00ac 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index d41f3a1646b5975..3f2ea0c467eba18 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 322e16ad9aa22f5..630f9ae5ba45d65 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index d14aa96f3afd9dc..8cebc141fcfe635 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 3b2525a9ad3695d..2376b3f9833cc79 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 0e74307b287b1d6..6adc75c259b698e 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index 711232cfe5fb938..c081c1bbced5506 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 8ef7302f9424016..3119fabc5f37635 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index 1e96537369f4f68..d5edbd94b2c2d77 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index d597eab6040d86d..2f9c46a12ce4b73 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index bc74060ed5772f4..e4a8b366fd82277 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index 788080974bd5115..03b2a7c0d59da1e 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index cc08902fb5188e3..67eda864aecef54 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index 368c6bc4c4e17a1..812e5819dbf027b 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 18c5537e517cb37..456ee4d75797e4b 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index be055d3421f943a..142fcef93a7cbba 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index e37546fd380acd8..2047124ddc76e1e 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index d67e37722eefa8d..8b9a47457e0b1e0 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 1085838afc40893..a06b76a37e11f7a 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index 6a588b79f975774..cecb6cc1e3823e9 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index 147dc8c0f2a59bb..1c8f445dfa98a86 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index fe87156b5c66830..f41972b2e8740be 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 844b5f816f9d18f..c93fbc0edd3d616 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index dec2bf4ad963ea1..280fc2e531e3e00 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 8898a25ac0bcf1a..b203ed4e1244fff 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 98f0aa3db8f4d34..3c9bac9a6824801 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index 9f27424fe732cbf..0c2bb1703a4d21b 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index d030876c628bf7c..cfeeca687deeffe 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index aa55ccbb1748d57..df1e89d8b8c7b94 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 32c47e205cad3b1..ebc71a327ec4098 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 4000cf70ef354ef..fa8261051cd9a2d 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index 02b900ed46c8fdb..aee085c84fdd6d1 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 23bb27798320a8d..f02671b9269d8dd 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 63b8babc853b564..77854ae4b9b3d34 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index b2662c15b897155..094f9b582de057b 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 1dc02e10800b9b8..6aa158c5b6a5462 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 42e61d8181d68bf..82c1f6a35c39310 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 8c56651fbebb1cc..90f871b5755badc 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 7f7bd24ba0c2525..4457d0a4d179e08 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index de515f8c7f8adaa..61e81f47ad0be51 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 5fb82f50bdb0830..fe7fa0727fca803 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 4f9980a966eaab6..c993e6381ab2518 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index c475f49c8e299d1..1e1e1e685cd3e13 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index aefc79053ce57f1..0c13e41ba0bf5ad 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 51ca5027e580fd3..9e8c59914f535b0 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 3704d558f29ba2f..c160a35aec5856f 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index 29c200e6c7b10b6..4f9c85545b9baaa 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 2d20766bc69c080..612558fb6174321 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index b7b0adca992944f..8dcf122a7d6331c 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 5cd13609582bb8a..3c15a08af87d2f7 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 4d5d4e3923720be..d1fd0830a12f562 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 8b477009cdb95bd..4dfdaf49b4dc443 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 1d2b050251a5b72..4ba102596dbe93e 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 204e28eee45552d..42fa2371f4e511f 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index bef09fb754efbb1..fc4b614ef54ecce 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 60315edc317c350..36d5c0a90442d14 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index b82b7d5c7b4d792..575b628869013ee 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index 717ee86e55c7ec5..cb2f6ebbdf1b2f7 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index a7c169ff83d11fc..3d675643fdaf060 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 4930f203b4d3143..512376932796256 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index be7858f7141b0a8..39edf10ab810799 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index a8cd1d2b12ee8c1..59075e448c06a32 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index 05c0c903a94cf3e..1d773e8d1edc2da 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 1b3e7230e7a47e1..e24befea2df1af5 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index ca7bf03727b1dee..bc94d89b1efa375 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 6c35510c6fcbee2..6604cd812cd1274 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_url_state.mdx b/api_docs/kbn_url_state.mdx index acc55a2c58ef202..39f2cfa25953959 100644 --- a/api_docs/kbn_url_state.mdx +++ b/api_docs/kbn_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-url-state title: "@kbn/url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/url-state plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/url-state'] --- import kbnUrlStateObj from './kbn_url_state.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index e4655b902d7c4e7..46de6d9ffeb8667 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index e5cc721c591cd2f..92c5de9de30c0f7 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 623c696c325234d..7ac642761b2087d 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index d455351d12fbda9..0997949b707e359 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 2bd8d140a4b6943..e2e37c0b21a84dc 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 8d84d15c0c9e5fb..e17f416fbedeaa5 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index cb864282cc482fb..215212639177b97 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index da6598826e036d3..da1fafbd3e4bbfc 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 3d5f466074404c7..df5e2daa1f4a20e 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 62accaa41e2d3b6..a69c1085f643e92 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 37d08523a04f116..bd702fd9bc1d701 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 6e73c1caea6a26c..44ace296ea33576 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index c2e3dcfdc3a0bb9..293f264fe09c348 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 63400fb38d55298..753533566c3822f 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 77f47a39755ba77..6f269f9cb6fe82a 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index dcd379357d65f2a..88a33810a955e9a 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 4da020544e63c50..e1f6c924637d0a8 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 42a5da260f7d0a8..ba3d8c90182d9fa 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index b11c3748f946287..e6bbb14d0e35648 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index fa19420f6451e03..365cc1b00e0fb27 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 935a87328d2872e..3473d0afa2ba7dd 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index cbd80bf72635b2a..28a5aef69fb73f8 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 589829b4862ff38..e6037075f87e684 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 3e382d21354d017..30cd99faa928413 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 014a586b294ce11..8e05854a0c5f477 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 09393b66217b2dc..68ccd5d5fe02550 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -12545,7 +12545,7 @@ "label": "value", "description": [], "signature": [ - "false" + "true" ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 6d70def76e0961d..19984f812269d39 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index 7bd14321e9e9812..dea3d730f616b97 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index 8e0ddc97770ec14..e25df5eeadfba71 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 0c0b447657dae8f..6539dc2c669944c 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 13e73af3a2016fe..3ad1ec4aa017280 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 71603 | 555 | 61304 | 1462 | +| 71609 | 555 | 61310 | 1463 | ## Plugin Directory @@ -30,7 +30,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 275 | 10 | 269 | 27 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 36 | 1 | 32 | 2 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 44 | 0 | 27 | 1 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 795 | 1 | 765 | 48 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 784 | 1 | 754 | 47 | | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 48 | 0 | 48 | 113 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | Asset manager plugin for entity assets (inventory, topology, etc) | 3 | 0 | 3 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 9 | 0 | 9 | 0 | @@ -63,7 +63,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | 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. | 1009 | 0 | 243 | 2 | | | [@elastic/ml-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 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 12 | 0 | 10 | 3 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 97 | 0 | 71 | 14 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 105 | 0 | 79 | 14 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | discoverLogExplorer | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | This plugin exposes and registers Logs+ features. | 0 | 0 | 0 | 0 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | APIs used to assess the quality of data in Elasticsearch indexes | 2 | 0 | 0 | 0 | @@ -90,11 +90,11 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression XY plugin adds a `xy` renderer and function to the expression plugin. The renderer will display the `xy` chart. | 175 | 0 | 165 | 13 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds expression runtime to Kibana | 2205 | 74 | 1746 | 5 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 235 | 0 | 99 | 2 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Index pattern fields and ambiguous values formatters | 288 | 26 | 249 | 3 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Index pattern fields and ambiguous values formatters | 292 | 26 | 253 | 3 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 239 | 0 | 24 | 9 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Simple UI for managing files in Kibana | 2 | 1 | 2 | 0 | -| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1182 | 3 | 1066 | 40 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1183 | 3 | 1067 | 40 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 0 | 0 | 0 | 0 | @@ -140,7 +140,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 218 | 8 | 164 | 11 | | | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 19 | 2 | 19 | 3 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 4 | 0 | 4 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 38 | 0 | 18 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 42 | 0 | 22 | 5 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Currently PDF, PNG or CSV export types for the reporting plugin | 4 | 0 | 4 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 21 | 0 | 21 | 0 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 266 | 0 | 237 | 14 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index c1582106748f09e..d7487e26c3ef372 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 114469c3f7a09fc..39ebcf98f518976 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 03932a0cfa43146..5058ca53474ef30 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index dc999b0fd3f024f..186cf1f65edae81 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 38 | 0 | 18 | 3 | +| 42 | 0 | 22 | 5 | ## Client diff --git a/api_docs/reporting_export_types.mdx b/api_docs/reporting_export_types.mdx index f9657b69a490c85..40cd784270a8afa 100644 --- a/api_docs/reporting_export_types.mdx +++ b/api_docs/reporting_export_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reportingExportTypes title: "reportingExportTypes" image: https://source.unsplash.com/400x175/?github description: API docs for the reportingExportTypes plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reportingExportTypes'] --- import reportingExportTypesObj from './reporting_export_types.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 00638cf519637ef..c43e648694e1208 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 491d7df29127fc2..561b036bd533ff7 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 98716dc4eeda7ba..9e82bedd4b1b869 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index ce889dfd15a7ef1..7a79df35cfb410a 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 3a1c48f52f4997e..3905714212cf73c 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.devdocs.json b/api_docs/saved_objects_management.devdocs.json index e1a1f39f7171887..44279045cfc4797 100644 --- a/api_docs/saved_objects_management.devdocs.json +++ b/api_docs/saved_objects_management.devdocs.json @@ -298,9 +298,7 @@ "Interpolation", "<", "Theme", - ">; abbr?: string | undefined; footer?: string | React.ReactElement> | ((props: ", - "EuiTableFooterProps", - "<", + ">; field: (string & {}) | keyof ", { "pluginId": "savedObjectsManagement", "scope": "public", @@ -308,7 +306,9 @@ "section": "def-public.SavedObjectsManagementRecord", "text": "SavedObjectsManagementRecord" }, - ">) => React.ReactNode) | undefined; field: (string & {}) | keyof ", + "; abbr?: string | undefined; footer?: string | React.ReactElement> | ((props: ", + "EuiTableFooterProps", + "<", { "pluginId": "savedObjectsManagement", "scope": "public", @@ -316,7 +316,7 @@ "section": "def-public.SavedObjectsManagementRecord", "text": "SavedObjectsManagementRecord" }, - "; width?: string | undefined; headers?: string | undefined; height?: string | number | undefined; readOnly?: boolean | undefined; dataType?: ", + ">) => React.ReactNode) | undefined; width?: string | undefined; headers?: string | undefined; height?: string | number | undefined; readOnly?: boolean | undefined; dataType?: ", "EuiTableDataType", " | undefined; render?: ((value: any, record: ", { diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index f749001f888fa4e..2236cf4edc9bb11 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 62e4df6d2d9f7b2..594e2cd375994a1 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 8e700f8fa36b850..38d4d20d8e71128 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index f5e8b8d17e3ba3d..62543715c4942b7 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 6123c29017cf5f8..c2b507833d8cb08 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 1dda98e525030f3..adc58346c0d24f4 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index d6b61f6cc79a98e..464640a25f6bc81 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index c9a7ac2fef781fa..85c5cab59613546 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index c39c09e736d3c3a..1a8a6e5a552f555 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index b4c6f48e87652cd..b3fd92cbf519aa6 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index 871e51d7662114d..a5e3a97f49a995f 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index f43b43ed995d7c2..b0a63e4a8bd37a0 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index c8934f3c83ef03e..93954a49230cf89 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 9b5ef8b7f64a17b..accb598d9da6282 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 46bc7a7c9d58bb7..ab1bdfa33da9455 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 124ae47a1a12060..74a2c4e199aaf79 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index d9e873ba9b8cca2..bba2c2f667b681d 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index a35981ac30f7557..2805925b996fc5b 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 2e5e6b05314f3d0..5aa3c839e35e1a3 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index ddaa0de4d4785d9..67a51883d95ee71 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 5dc14d03266e593..ac42be59aaa796b 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 7e6d3244a3c6d3f..bc53bfc85354606 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 1967e48e0d35f81..335cd4bfb06f94c 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 6cc30c6dceec1b2..abe8ddb1f33f78f 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index fc979b78d4ed3f3..501d3beb4db8723 100644 --- a/api_docs/text_based_languages.mdx +++ b/api_docs/text_based_languages.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/textBasedLanguages title: "textBasedLanguages" image: https://source.unsplash.com/400x175/?github description: API docs for the textBasedLanguages plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index bcb463932cc8107..0f014215df2a0fe 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index b915dd667c37de7..a7d69e47be02471 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index b58f892e2ec8abb..619a2d3285f2650 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index ccfc51a8dbf0640..0c2c5cc3a3db73f 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 079af58f8da48ba..6b9a3a9567cc373 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 17c83c55907f891..48c8b6265b8b6db 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index ef0673dbcd20f38..0cad6de177c52f2 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index db680b850215eda..9c42d4c6eb9b629 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index e96c63cc88fe92d..78ea5e1ad11eca4 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index 5de3964976395ac..9e3b41f51c89791 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 8885eebcea481dc..18749c1c1c0f65d 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index e9c715cf33ee3eb..7b1ec547c57b245 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 8fe33670600642a..4a7996e9a52ea74 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 163fbb637a01c92..77578960aa9109e 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 32e853193b01d5a..1fbdf47c1c7396a 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 045b070a466d97c..3642a985532d2c0 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 63a9238b253360b..40d9ff4a68637ed 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 1fb4112154caae8..dd3b54b9461cd02 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 5a6c6d4c0ecb428..7037e0c9d677138 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index cefad2d8232240c..fdbd9f01ca9b072 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index fea43ea7302377f..bbb2f9ca7443594 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 6ccfd5f61431477..aa2dcf3a23dd58d 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 82860f6c86936c6..a669c0296354bfd 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2023-07-24 +date: 2023-07-25 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 08c8b3d7ffea4b0d9cb8271d396f2c95cf879766 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 25 Jul 2023 08:26:28 +0200 Subject: [PATCH 02/29] [ZDT] document behavior of the `fields` find option for serverless (#162404) ## Summary Fix https://github.com/elastic/kibana/issues/153766 Add documentation on the limitation of using the `fields` option of the `SOR.find` API on managed environments. --- .../src/lib/apis/find.ts | 12 +++++---- .../src/apis/find.ts | 20 ++++++++++++-- .../docs/model_versions.md | 26 ++++++++++++++++++- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/find.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/find.ts index 4fa0068313b5117..3346e6552646af4 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/find.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/apis/find.ts @@ -239,11 +239,13 @@ export const performFind = async ( total: body.hits.total, saved_objects: body.hits.hits.map( (hit: estypes.SearchHit): SavedObjectsFindResult => { - const savedObject = migrationHelper.migrateStorageDocument( - serializerHelper.rawToSavedObject(hit as SavedObjectsRawDoc, { - migrationVersionCompatibility, - }) - ) as SavedObject; + let savedObject = serializerHelper.rawToSavedObject(hit as SavedObjectsRawDoc, { + migrationVersionCompatibility, + }); + // can't migrate a document with partial attributes + if (!fields) { + savedObject = migrationHelper.migrateStorageDocument(savedObject) as SavedObject; + } return { ...savedObject, score: hit._score!, diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts index af8a265673f4da3..e0e035abea34b8c 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/find.ts @@ -56,9 +56,25 @@ export interface SavedObjectsFindOptions { /** sort order, ascending or descending */ sortOrder?: SortOrder; /** - * An array of fields to include in the results + * An array of attributes to fetch and include in the results. If unspecified, all attributes will be fetched. + * + * The main purpose of this option is to avoid fetching unnecessary heavy fields (e.g blobs) when searching for + * savedObjects, for performance purposes. + * + * Defaults to `undefined` (fetching all fields). + * * @example - * SavedObjects.find({type: 'dashboard', fields: ['attributes.name', 'attributes.location']}) + * ```ts + * SavedObjects.find({type: 'dashboard', fields: ['name', 'description']}) + * ``` + * + * @remarks When this option is specified, the savedObjects returned from the API will not + * go through the migration process (as we can't migrate partial documents). + * For this reason, all fields provided to this option should already be present + * in the prior model version of the document's SO type. + * Otherwise, it may lead to inconsistencies during hybrid version cohabitation + * (e.g during an upgrade in serverless) where newly introduced / backfilled fields + * may not necessarily appear in the documents returned from the API when the option is used. */ fields?: string[]; /** Search documents using the Elasticsearch Simple Query String syntax. See Elasticsearch Simple Query String `query` argument for more information */ diff --git a/packages/core/saved-objects/core-saved-objects-server/docs/model_versions.md b/packages/core/saved-objects/core-saved-objects-server/docs/model_versions.md index ca70bfcbd0c78c2..ba04303fbd0c808 100644 --- a/packages/core/saved-objects/core-saved-objects-server/docs/model_versions.md +++ b/packages/core/saved-objects/core-saved-objects-server/docs/model_versions.md @@ -13,6 +13,8 @@ - [Adding an indexed field without default value](#adding-an-indexed-field-without-default-value) - [Adding an indexed field with a default value](#adding-an-indexed-field-with-a-default-value) - [Removing an existing field](#removing-an-existing-field) +- [Particularities of the serverless environment](#particularities-of-the-serverless-environment) + - [Using the fields option of the find api](#using-the-fields-option-of-the-find-savedobjects-api) ## Introduction @@ -866,4 +868,26 @@ const myType: SavedObjectsType = { }, }, }; -``` \ No newline at end of file +``` + +## Particularities of the serverless environment + +The serverless environment, and the fact that upgrade in such environments are performed in a way +where, at some point, the old and new version of the application are living in cohabitation, leads +to some particularities regarding the way the SO APIs works, and to some limitations / edge case +that we need to document + +### Using the `fields` option of the `find` savedObjects API + +By default, the `find` API (as any other SO API returning documents) will migrate all documents before +returning them, to ensure that documents can be used by both versions during a cohabitation (e.g an old +node searching for documents already migrated, or a new node searching for documents not yet migrated). + +However, when using the `fields` option of the `find` API, the documents can't be migrated, as some +model version changes can't be applied against a partial set of attributes. For this reason, when the +`fields` option is provided, the documents returned from `find` will **not** be migrated. + +Which is why, when using this option, the API consumer needs to make sure that *all* the fields passed +to the `fields` option **were already present in the prior model version**. Otherwise, it may lead to inconsistencies +during upgrades, where newly introduced or backfilled fields may not necessarily appear in the documents returned +from the `search` API when the option is used. From a79e9c737498bc3f3bda3d82ef1b3387be88b9ed Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 25 Jul 2023 10:04:44 +0200 Subject: [PATCH 03/29] Remove eslint-plugin-prefer-object-spread dependency (#162439) Remove the `eslint-plugin-prefer-object-spread` dependency as the `prefer-object-spread` rule has been part of ESLint since v5 --- .eslintrc.js | 6 +++--- package.json | 1 - packages/kbn-eslint-config/javascript.js | 3 +-- packages/kbn-eslint-config/typescript.js | 1 - packages/kbn-tinymath/src/index.js | 2 +- yarn.lock | 5 ----- 6 files changed, 5 insertions(+), 13 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index dacfa2d470e059a..de3adc0913fc98f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -639,7 +639,7 @@ module.exports = { files: ['scripts/**/*.js', 'src/setup_node_env/**/*.js'], rules: { 'import/no-commonjs': 'off', - 'prefer-object-spread/prefer-object-spread': 'off', + 'prefer-object-spread': 'off', 'no-var': 'off', 'prefer-const': 'off', 'prefer-destructuring': 'off', @@ -672,7 +672,7 @@ module.exports = { '**/browser_exec_scripts/**/*.js', ], rules: { - 'prefer-object-spread/prefer-object-spread': 'off', + 'prefer-object-spread': 'off', 'no-var': 'off', 'prefer-const': 'off', 'prefer-destructuring': 'off', @@ -708,7 +708,7 @@ module.exports = { excludedFiles: ['**/integration_tests/**/*'], rules: { 'import/no-commonjs': 'off', - 'prefer-object-spread/prefer-object-spread': 'off', + 'prefer-object-spread': 'off', 'no-restricted-syntax': [ 'error', 'ImportDeclaration', diff --git a/package.json b/package.json index e5295bc888c3b95..819c6b28a6fdd27 100644 --- a/package.json +++ b/package.json @@ -1423,7 +1423,6 @@ "eslint-plugin-mocha": "^10.0.5", "eslint-plugin-no-unsanitized": "^3.1.5", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prefer-object-spread": "^1.2.1", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.26.1", "eslint-plugin-react-hooks": "^4.2.0", diff --git a/packages/kbn-eslint-config/javascript.js b/packages/kbn-eslint-config/javascript.js index d048d9a93bdda0c..31f918546c12672 100644 --- a/packages/kbn-eslint-config/javascript.js +++ b/packages/kbn-eslint-config/javascript.js @@ -15,7 +15,6 @@ module.exports = { '@babel', 'import', 'no-unsanitized', - 'prefer-object-spread', ], env: { @@ -94,7 +93,7 @@ module.exports = { 'import/no-duplicates': 'error', 'import/no-dynamic-require': 'error', - 'prefer-object-spread/prefer-object-spread': 'error', + 'prefer-object-spread': 'error', } }, ] diff --git a/packages/kbn-eslint-config/typescript.js b/packages/kbn-eslint-config/typescript.js index 04e847224df58b8..d62314c97d547c7 100644 --- a/packages/kbn-eslint-config/typescript.js +++ b/packages/kbn-eslint-config/typescript.js @@ -20,7 +20,6 @@ module.exports = { '@typescript-eslint', 'ban', 'import', - 'prefer-object-spread', 'eslint-comments' ], diff --git a/packages/kbn-tinymath/src/index.js b/packages/kbn-tinymath/src/index.js index 5bc7d80faff9e4b..be4b42ca93be1eb 100644 --- a/packages/kbn-tinymath/src/index.js +++ b/packages/kbn-tinymath/src/index.js @@ -35,7 +35,7 @@ function evaluate(expression, scope = {}, injectedFunctions = {}) { } function interpret(node, scope, injectedFunctions) { - const functions = Object.assign({}, includedFunctions, injectedFunctions); // eslint-disable-line prefer-object-spread/prefer-object-spread + const functions = Object.assign({}, includedFunctions, injectedFunctions); // eslint-disable-line prefer-object-spread return exec(node); function exec(node) { diff --git a/yarn.lock b/yarn.lock index 3aafb5c0e7810c4..ec7ff3a02eeba6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15380,11 +15380,6 @@ eslint-plugin-node@^11.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prefer-object-spread@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-object-spread/-/eslint-plugin-prefer-object-spread-1.2.1.tgz#27fb91853690cceb3ae6101d9c8aecc6a67a402c" - integrity sha1-J/uRhTaQzOs65hAdnIrsxqZ6QCw= - eslint-plugin-prettier@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0" From 70b337a1353a63ff536dbd45fce5648a58ffff87 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 25 Jul 2023 10:09:05 +0200 Subject: [PATCH 04/29] Fix @kbn/import-resolver detection of nested node_modules (#162391) Ensure that a plugin containing a nested `node_modules` folder correctly identifies imports from that folder as regular node modules instead of relative imports. Kibana should currently only have a single root `node_modules` folder, so this should not be a real issue. However, if for some reason a stray `node_modules` folder is created, this commit will make sure it's not introducing hard to debug ESLint errors. --- .gitignore | 1 + .../packages/box/node_modules/bar/index.js | 0 packages/kbn-import-resolver/src/import_resolver.ts | 2 +- .../src/integration_tests/import_resolver.test.ts | 11 +++++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 packages/kbn-import-resolver/src/__fixtures__/packages/box/node_modules/bar/index.js diff --git a/.gitignore b/.gitignore index 86a789a1cfb5f79..0107ffdef5e1996 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ node_modules !/src/dev/npm/integration_tests/__fixtures__/fixture1/node_modules !/src/dev/notice/__fixtures__/node_modules !/packages/kbn-import-resolver/src/__fixtures__/node_modules +!/packages/kbn-import-resolver/src/__fixtures__/packages/box/node_modules trash /optimize /built_assets diff --git a/packages/kbn-import-resolver/src/__fixtures__/packages/box/node_modules/bar/index.js b/packages/kbn-import-resolver/src/__fixtures__/packages/box/node_modules/bar/index.js new file mode 100644 index 000000000000000..e69de29bb2d1d64 diff --git a/packages/kbn-import-resolver/src/import_resolver.ts b/packages/kbn-import-resolver/src/import_resolver.ts index 2ad76e9b5a7eb75..ee1f168d693a169 100644 --- a/packages/kbn-import-resolver/src/import_resolver.ts +++ b/packages/kbn-import-resolver/src/import_resolver.ts @@ -86,7 +86,7 @@ export class ImportResolver { getPackageIdForPath(path: string) { const relative = Path.relative(this.cwd, path); - if (relative.startsWith('..')) { + if (relative.startsWith('..') || path.includes(NODE_MODULE_SEG)) { return null; } diff --git a/packages/kbn-import-resolver/src/integration_tests/import_resolver.test.ts b/packages/kbn-import-resolver/src/integration_tests/import_resolver.test.ts index e26e37e1495e588..f286848700495e9 100644 --- a/packages/kbn-import-resolver/src/integration_tests/import_resolver.test.ts +++ b/packages/kbn-import-resolver/src/integration_tests/import_resolver.test.ts @@ -42,6 +42,17 @@ describe('#resolve()', () => { `); }); + it('resolves nested node_module imports', () => { + expect(resolver.resolve('bar', Path.join(FIXTURES_DIR, 'packages', 'box'))) + .toMatchInlineSnapshot(` + Object { + "absolute": /packages/kbn-import-resolver/src/__fixtures__/packages/box/node_modules/bar/index.js, + "nodeModule": "bar", + "type": "file", + } + `); + }); + it('resolves requests to src/', () => { expect(resolver.resolve('src/core/public', FIXTURES_DIR)).toMatchInlineSnapshot(` Object { From 5f70b4b8ebf778db80db7c237346bf0653d191e5 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 25 Jul 2023 10:09:55 +0200 Subject: [PATCH 05/29] Clean up imports of ESLint types (#162436) --- .../kbn-eslint-plugin-disable/src/helpers/regex.ts | 12 ++++++------ .../kbn-eslint-plugin-disable/src/helpers/report.ts | 4 ++-- .../src/rules/no_naked_eslint_disable.ts | 10 +++++----- .../src/rules/no_protected_eslint_disable.ts | 12 ++++++------ .../src/get_import_resolver.ts | 2 +- .../kbn-eslint-plugin-imports/src/helpers/report.ts | 4 ++-- .../kbn-eslint-plugin-imports/src/helpers/source.ts | 2 +- .../src/helpers/visit_all_import_statements.ts | 2 +- .../src/rules/exports_moved_packages.ts | 2 +- .../src/rules/no_boundary_crossing.ts | 2 +- .../src/rules/no_unresolvable_imports.ts | 2 +- .../src/rules/no_unused_imports.ts | 2 +- .../src/rules/uniform_imports.ts | 4 ++-- 13 files changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/kbn-eslint-plugin-disable/src/helpers/regex.ts b/packages/kbn-eslint-plugin-disable/src/helpers/regex.ts index b2627654c1b6557..4cf9f776ff45ba4 100644 --- a/packages/kbn-eslint-plugin-disable/src/helpers/regex.ts +++ b/packages/kbn-eslint-plugin-disable/src/helpers/regex.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type Eslint from 'eslint'; +import type { AST } from 'eslint'; const ESLINT_DISABLE_RE = /^eslint-disable(?:-next-line|-line)?(?.*)/; @@ -17,16 +17,16 @@ export enum ESLINT_DISABLE_VALUE { } export interface ParsedEslintDisableComment { - type: Eslint.AST.Program['comments'][0]['type']; - range: Eslint.AST.Program['comments'][0]['range']; - loc: Eslint.AST.Program['comments'][0]['loc']; - value: Eslint.AST.Program['comments'][0]['value']; + type: AST.Program['comments'][0]['type']; + range: AST.Program['comments'][0]['range']; + loc: AST.Program['comments'][0]['loc']; + value: AST.Program['comments'][0]['value']; disableValueType: ESLINT_DISABLE_VALUE; rules: string[]; } export function parseEslintDisableComment( - comment: Eslint.AST.Program['comments'][0] + comment: AST.Program['comments'][0] ): ParsedEslintDisableComment | undefined { const commentVal = comment.value.trim(); const nakedESLintRegexResult = commentVal.match(ESLINT_DISABLE_RE); diff --git a/packages/kbn-eslint-plugin-disable/src/helpers/report.ts b/packages/kbn-eslint-plugin-disable/src/helpers/report.ts index a497cefb9d14805..03d196dc531866a 100644 --- a/packages/kbn-eslint-plugin-disable/src/helpers/report.ts +++ b/packages/kbn-eslint-plugin-disable/src/helpers/report.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import type Eslint from 'eslint'; +import type { AST } from 'eslint'; import { ESLINT_DISABLE_VALUE, ParsedEslintDisableComment } from './regex'; export function getReportLocFromComment( comment: ParsedEslintDisableComment -): Eslint.AST.SourceLocation | undefined { +): AST.SourceLocation | undefined { const cStart = comment?.loc?.start; const cEnd = comment?.loc?.end; const cStartLine = comment?.loc?.start?.line; diff --git a/packages/kbn-eslint-plugin-disable/src/rules/no_naked_eslint_disable.ts b/packages/kbn-eslint-plugin-disable/src/rules/no_naked_eslint_disable.ts index 45660dbf20a6d13..84ca09088b7e414 100644 --- a/packages/kbn-eslint-plugin-disable/src/rules/no_naked_eslint_disable.ts +++ b/packages/kbn-eslint-plugin-disable/src/rules/no_naked_eslint_disable.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import Eslint from 'eslint'; +import type { Rule, AST } from 'eslint'; import { getReportLocFromComment, parseEslintDisableComment } from '../helpers'; export const NAKED_DISABLE_MSG_ID = 'no-naked-eslint-disable'; @@ -15,7 +15,7 @@ const messages = { 'Using a naked eslint disable is not allowed. Please specify the specific rules to disable.', }; -const meta: Eslint.Rule.RuleMetaData = { +const meta: Rule.RuleMetaData = { type: 'problem', fixable: 'code', docs: { @@ -25,7 +25,7 @@ const meta: Eslint.Rule.RuleMetaData = { messages, }; -const create = (context: Eslint.Rule.RuleContext): Eslint.Rule.RuleListener => { +const create = (context: Rule.RuleContext): Rule.RuleListener => { return { Program(node) { const nodeComments = node.comments || []; @@ -56,7 +56,7 @@ const create = (context: Eslint.Rule.RuleContext): Eslint.Rule.RuleListener => { loc: reportLoc, messageId: NAKED_DISABLE_MSG_ID, fix(fixer) { - return fixer.removeRange(parsedEslintDisable.range as Eslint.AST.Range); + return fixer.removeRange(parsedEslintDisable.range as AST.Range); }, }); }); @@ -64,7 +64,7 @@ const create = (context: Eslint.Rule.RuleContext): Eslint.Rule.RuleListener => { }; }; -export const NoNakedESLintDisableRule: Eslint.Rule.RuleModule = { +export const NoNakedESLintDisableRule: Rule.RuleModule = { meta, create, }; diff --git a/packages/kbn-eslint-plugin-disable/src/rules/no_protected_eslint_disable.ts b/packages/kbn-eslint-plugin-disable/src/rules/no_protected_eslint_disable.ts index bffcd5c2febc0b5..93e86f2423d8a7b 100644 --- a/packages/kbn-eslint-plugin-disable/src/rules/no_protected_eslint_disable.ts +++ b/packages/kbn-eslint-plugin-disable/src/rules/no_protected_eslint_disable.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import Eslint from 'eslint'; +import type { Rule, AST } from 'eslint'; import { PROTECTED_RULES, getReportLocFromComment, parseEslintDisableComment } from '../helpers'; export const PROTECTED_DISABLE_MSG_ID = 'no-protected-eslint-disable'; @@ -15,7 +15,7 @@ const messages = { "The rule '{{ disabledRuleName }}' is protected and disabling it is not allowed. Please remove it from the statement.", }; -const meta: Eslint.Rule.RuleMetaData = { +const meta: Rule.RuleMetaData = { type: 'problem', fixable: 'code', docs: { @@ -24,7 +24,7 @@ const meta: Eslint.Rule.RuleMetaData = { messages, }; -const create = (context: Eslint.Rule.RuleContext): Eslint.Rule.RuleListener => { +const create = (context: Rule.RuleContext): Rule.RuleListener => { return { Program(node) { const nodeComments = node.comments || []; @@ -68,7 +68,7 @@ const create = (context: Eslint.Rule.RuleContext): Eslint.Rule.RuleListener => { fix(fixer) { // if we only have a single disabled rule and that is protected, we can remove the entire comment if (disabledRules.length === 1) { - return fixer.removeRange(parsedEslintDisable.range as Eslint.AST.Range); + return fixer.removeRange(parsedEslintDisable.range as AST.Range); } // it's impossible to fix as we don't have a range @@ -80,7 +80,7 @@ const create = (context: Eslint.Rule.RuleContext): Eslint.Rule.RuleListener => { const fixedComment = ` ${parsedEslintDisable.disableValueType} ${remainingRules.join( ', ' )}${parsedEslintDisable.type === 'Block' ? ' ' : ''}`; - const rangeToFix: Eslint.AST.Range = + const rangeToFix: AST.Range = parsedEslintDisable.type === 'Line' ? [parsedEslintDisable.range[0] + 2, parsedEslintDisable.range[1]] : [parsedEslintDisable.range[0] + 2, parsedEslintDisable.range[1] - 2]; @@ -93,7 +93,7 @@ const create = (context: Eslint.Rule.RuleContext): Eslint.Rule.RuleListener => { }; }; -export const NoProtectedESLintDisableRule: Eslint.Rule.RuleModule = { +export const NoProtectedESLintDisableRule: Rule.RuleModule = { meta, create, }; diff --git a/packages/kbn-eslint-plugin-imports/src/get_import_resolver.ts b/packages/kbn-eslint-plugin-imports/src/get_import_resolver.ts index 8679dd73b022350..6a05298f4ab42c0 100644 --- a/packages/kbn-eslint-plugin-imports/src/get_import_resolver.ts +++ b/packages/kbn-eslint-plugin-imports/src/get_import_resolver.ts @@ -8,7 +8,7 @@ import { ImportResolver } from '@kbn/import-resolver'; import { REPO_ROOT } from '@kbn/repo-info'; -import { Rule } from 'eslint'; +import type { Rule } from 'eslint'; import { RUNNING_IN_EDITOR } from './helpers/running_in_editor'; let importResolverCache: ImportResolver | undefined; diff --git a/packages/kbn-eslint-plugin-imports/src/helpers/report.ts b/packages/kbn-eslint-plugin-imports/src/helpers/report.ts index bfcd9956018cce8..4ac96a208ce06b6 100644 --- a/packages/kbn-eslint-plugin-imports/src/helpers/report.ts +++ b/packages/kbn-eslint-plugin-imports/src/helpers/report.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import Eslint from 'eslint'; +import type { Rule } from 'eslint'; import { SomeNode } from './visit_all_import_statements'; interface ReportOptions { @@ -18,7 +18,7 @@ interface ReportOptions { /** * Simple wrapper around context.report so that the types work better with typescript-estree */ -export function report(context: Eslint.Rule.RuleContext, options: ReportOptions) { +export function report(context: Rule.RuleContext, options: ReportOptions) { context.report({ node: options.node as any, message: options.message, diff --git a/packages/kbn-eslint-plugin-imports/src/helpers/source.ts b/packages/kbn-eslint-plugin-imports/src/helpers/source.ts index 8bb98832f311858..eba1300b7cbbe92 100644 --- a/packages/kbn-eslint-plugin-imports/src/helpers/source.ts +++ b/packages/kbn-eslint-plugin-imports/src/helpers/source.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Rule } from 'eslint'; +import type { Rule } from 'eslint'; /** * Get the path of the sourcefile being linted diff --git a/packages/kbn-eslint-plugin-imports/src/helpers/visit_all_import_statements.ts b/packages/kbn-eslint-plugin-imports/src/helpers/visit_all_import_statements.ts index 6f549d93ef26e0d..4e71191cb6efdfe 100644 --- a/packages/kbn-eslint-plugin-imports/src/helpers/visit_all_import_statements.ts +++ b/packages/kbn-eslint-plugin-imports/src/helpers/visit_all_import_statements.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Rule } from 'eslint'; +import type { Rule } from 'eslint'; import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree'; import * as T from '@babel/types'; import { ImportType } from '@kbn/import-resolver'; diff --git a/packages/kbn-eslint-plugin-imports/src/rules/exports_moved_packages.ts b/packages/kbn-eslint-plugin-imports/src/rules/exports_moved_packages.ts index eb2bc90f2ba4fbe..19b4111a8caad8b 100644 --- a/packages/kbn-eslint-plugin-imports/src/rules/exports_moved_packages.ts +++ b/packages/kbn-eslint-plugin-imports/src/rules/exports_moved_packages.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Rule, AST } from 'eslint'; +import type { Rule, AST } from 'eslint'; import * as T from '@babel/types'; import { TSESTree } from '@typescript-eslint/typescript-estree'; diff --git a/packages/kbn-eslint-plugin-imports/src/rules/no_boundary_crossing.ts b/packages/kbn-eslint-plugin-imports/src/rules/no_boundary_crossing.ts index db4be34ba010938..2513922e9c9a8db 100644 --- a/packages/kbn-eslint-plugin-imports/src/rules/no_boundary_crossing.ts +++ b/packages/kbn-eslint-plugin-imports/src/rules/no_boundary_crossing.ts @@ -10,7 +10,7 @@ import Path from 'path'; import { TSESTree } from '@typescript-eslint/typescript-estree'; import * as Bt from '@babel/types'; -import { Rule } from 'eslint'; +import type { Rule } from 'eslint'; import ESTree from 'estree'; import { ModuleType } from '@kbn/repo-source-classifier'; diff --git a/packages/kbn-eslint-plugin-imports/src/rules/no_unresolvable_imports.ts b/packages/kbn-eslint-plugin-imports/src/rules/no_unresolvable_imports.ts index 9990ec38530e5e8..1edafe27affb35e 100644 --- a/packages/kbn-eslint-plugin-imports/src/rules/no_unresolvable_imports.ts +++ b/packages/kbn-eslint-plugin-imports/src/rules/no_unresolvable_imports.ts @@ -7,7 +7,7 @@ */ import Path from 'path'; -import { Rule } from 'eslint'; +import type { Rule } from 'eslint'; import { report } from '../helpers/report'; import { getSourcePath } from '../helpers/source'; diff --git a/packages/kbn-eslint-plugin-imports/src/rules/no_unused_imports.ts b/packages/kbn-eslint-plugin-imports/src/rules/no_unused_imports.ts index e3c196c5d560e9a..f12e149af9f665a 100644 --- a/packages/kbn-eslint-plugin-imports/src/rules/no_unused_imports.ts +++ b/packages/kbn-eslint-plugin-imports/src/rules/no_unused_imports.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Rule, Scope, AST } from 'eslint'; +import type { Rule, Scope, AST } from 'eslint'; import type { Comment } from 'estree'; import * as T from '@babel/types'; import { TSESTree } from '@typescript-eslint/typescript-estree'; diff --git a/packages/kbn-eslint-plugin-imports/src/rules/uniform_imports.ts b/packages/kbn-eslint-plugin-imports/src/rules/uniform_imports.ts index 6855a1359f43eb0..4cf4a5e0f1f331d 100644 --- a/packages/kbn-eslint-plugin-imports/src/rules/uniform_imports.ts +++ b/packages/kbn-eslint-plugin-imports/src/rules/uniform_imports.ts @@ -8,7 +8,7 @@ import Path from 'path'; -import Eslint from 'eslint'; +import type { Rule } from 'eslint'; import { getRelativeImportReq, getPackageRelativeImportReq } from '@kbn/import-resolver'; import { report } from '../helpers/report'; @@ -16,7 +16,7 @@ import { visitAllImportStatements } from '../helpers/visit_all_import_statements import { getSourcePath } from '../helpers/source'; import { getImportResolver } from '../get_import_resolver'; -export const UniformImportsRule: Eslint.Rule.RuleModule = { +export const UniformImportsRule: Rule.RuleModule = { meta: { fixable: 'code', docs: { From 7143dcf2c305818078c6c80896921e2e845cc156 Mon Sep 17 00:00:00 2001 From: Konrad Szwarc Date: Tue, 25 Jul 2023 10:19:19 +0200 Subject: [PATCH 06/29] [Defend Workflows] Reputation Service option added to Malicious Behavior Policy card (#161617) Closes https://github.com/elastic/security-team/issues/7051 **This PR still awaits a proper copy. For now, the info icon has a placeholder text.** To see these changes locally, negate this check https://github.com/elastic/kibana/pull/161617/files#diff-3d6bd044f37fc0d877d89113b0ca10f9bd64f2b4d3aaf28ecaecdfa70d379f82R89 Saved at `policy.[os]. behavior_protection.reputation_service: boolean` ![test](https://github.com/elastic/kibana/assets/29123534/0d78338c-e9d1-4441-ac74-31974f3702ea) --- .../group2/check_registered_types.test.ts | 2 +- .../fleet/server/saved_objects/index.ts | 20 ++- .../migrations/security_solution/index.ts | 1 + .../security_solution/to_v8_10_0.test.ts | 159 ++++++++++++++++++ .../security_solution/to_v8_10_0.ts | 69 ++++++++ .../common/endpoint/models/policy_config.ts | 6 + .../models/policy_config_helpers.test.ts | 24 ++- .../common/endpoint/types/index.ts | 10 +- .../policy/store/policy_details/index.test.ts | 18 +- .../cards/behaviour_protection_card.test.tsx | 7 +- .../behaviour_protection_card.tsx | 32 ++-- .../components/reputation_service.tsx | 137 +++++++++++++++ .../protection_setting_card_switch.tsx | 10 ++ .../policy_settings_form.tsx | 2 +- .../handlers/create_default_policy.test.ts | 27 ++- 15 files changed, 486 insertions(+), 38 deletions(-) create mode 100644 x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_10_0.test.ts create mode 100644 x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_10_0.ts rename x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/{ => protection_seetings_card}/behaviour_protection_card.tsx (72%) create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/protection_seetings_card/components/reputation_service.tsx diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts index c1cfca07017bccb..2a6048410736277 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts @@ -106,7 +106,7 @@ describe('checking migration metadata changes on all registered SO types', () => "ingest-agent-policies": "f11cc19275f4c3e4ee7c5cd6423b6706b21b989d", "ingest-download-sources": "d7edc5e588d9afa61c4b831604582891c54ef1c7", "ingest-outputs": "bffa0fd93dfdde904d7f5aff77df72d1c35938d9", - "ingest-package-policies": "7d0e8d288e193e0a8a153bb420c6056bc862c4c3", + "ingest-package-policies": "55816507db0134b8efbe0509e311a91ce7e1c6cc", "ingest_manager_settings": "418311b03c8eda53f5d2ea6f54c1356afaa65511", "inventory-view": "b8683c8e352a286b4aca1ab21003115a4800af83", "kql-telemetry": "93c1d16c1a0dfca9c8842062cf5ef8f62ae401ad", diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index 9ef02f826f8add6..b12ad9416e514c6 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -25,6 +25,8 @@ import { UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, } from '../constants'; +import { migratePackagePolicyEvictionsFromV8100 } from './migrations/security_solution/to_v8_10_0'; + import { migrateAgentPolicyToV7100, migratePackagePolicyToV7100, @@ -56,7 +58,10 @@ import { migrateInstallationToV860, migratePackagePolicyToV860, } from './migrations/to_v8_6_0'; -import { migratePackagePolicyToV870 } from './migrations/security_solution'; +import { + migratePackagePolicyToV8100, + migratePackagePolicyToV870, +} from './migrations/security_solution'; import { migratePackagePolicyToV880 } from './migrations/to_v8_8_0'; import { migrateAgentPolicyToV890 } from './migrations/to_v8_9_0'; @@ -269,6 +274,19 @@ const getSavedObjectTypes = (): { [key: string]: SavedObjectsType } => ({ created_by: { type: 'keyword' }, }, }, + modelVersions: { + '1': { + changes: [ + { + type: 'data_backfill', + backfillFn: migratePackagePolicyToV8100, + }, + ], + schemas: { + forwardCompatibility: migratePackagePolicyEvictionsFromV8100, + }, + }, + }, migrations: { '7.10.0': migratePackagePolicyToV7100, '7.11.0': migratePackagePolicyToV7110, diff --git a/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/index.ts b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/index.ts index 4dd924e832a22df..8248c181405e58a 100644 --- a/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/index.ts @@ -18,3 +18,4 @@ export { migratePackagePolicyToV850 } from './to_v8_5_0'; export { migratePackagePolicyToV860 } from './to_v8_6_0'; export { migratePackagePolicyToV870 } from './to_v8_7_0'; export { migratePackagePolicyToV880 } from './to_v8_8_0'; +export { migratePackagePolicyToV8100 } from './to_v8_10_0'; diff --git a/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_10_0.test.ts b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_10_0.test.ts new file mode 100644 index 000000000000000..e31653bd448e3f9 --- /dev/null +++ b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_10_0.test.ts @@ -0,0 +1,159 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SavedObjectUnsanitizedDoc } from '@kbn/core/server'; + +import type { SavedObjectModelTransformationContext } from '@kbn/core-saved-objects-server'; + +import type { PackagePolicy } from '../../../../common'; + +import { migratePackagePolicyToV8100 as migration } from './to_v8_10_0'; +import { migratePackagePolicyEvictionsFromV8100 as eviction } from './to_v8_10_0'; + +describe('8.10.0 Endpoint Package Policy migration', () => { + const policyDoc = ({ behaviorProtection = {} }) => { + return { + id: 'mock-saved-object-id', + attributes: { + name: 'Some Policy Name', + package: { + name: 'endpoint', + title: '', + version: '', + }, + id: 'endpoint', + policy_id: '', + enabled: true, + namespace: '', + revision: 0, + updated_at: '', + updated_by: '', + created_at: '', + created_by: '', + inputs: [ + { + type: 'endpoint', + enabled: true, + streams: [], + config: { + policy: { + value: { + meta: {}, + windows: { + behavior_protection: { + ...behaviorProtection, + }, + }, + mac: { + behavior_protection: { + ...behaviorProtection, + }, + }, + linux: { + behavior_protection: { + ...behaviorProtection, + }, + }, + }, + }, + }, + }, + ], + }, + type: ' nested', + }; + }; + + it('adds reputation service field to behaviour protection, set to false', () => { + const initialDoc = policyDoc({}); + + const migratedDoc = policyDoc({ + behaviorProtection: { reputation_service: false }, + }); + + expect(migration(initialDoc, {} as SavedObjectModelTransformationContext)).toEqual({ + attributes: { + inputs: migratedDoc.attributes.inputs, + }, + }); + }); + + it('removes reputation service field from behaviour protection', () => { + const initialDoc = policyDoc({ + behaviorProtection: { reputation_service: true }, + }); + + const migratedDoc = policyDoc({}); + + expect(eviction(initialDoc.attributes)).toEqual(migratedDoc.attributes); + }); + + it('does not modify non-endpoint package policies', () => { + const doc: SavedObjectUnsanitizedDoc = { + id: 'mock-saved-object-id', + attributes: { + name: 'Some Policy Name', + package: { + name: 'notEndpoint', + title: '', + version: '', + }, + id: 'notEndpoint', + policy_id: '', + enabled: true, + namespace: '', + revision: 0, + updated_at: '', + updated_by: '', + created_at: '', + created_by: '', + inputs: [ + { + type: 'notEndpoint', + enabled: true, + streams: [], + config: {}, + }, + ], + }, + type: ' nested', + }; + + expect( + migration( + doc, + {} as SavedObjectModelTransformationContext + ) as SavedObjectUnsanitizedDoc + ).toEqual({ + attributes: { + name: 'Some Policy Name', + package: { + name: 'notEndpoint', + title: '', + version: '', + }, + id: 'notEndpoint', + policy_id: '', + enabled: true, + namespace: '', + revision: 0, + updated_at: '', + updated_by: '', + created_at: '', + created_by: '', + inputs: [ + { + type: 'notEndpoint', + enabled: true, + streams: [], + config: {}, + }, + ], + }, + }); + }); +}); diff --git a/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_10_0.ts b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_10_0.ts new file mode 100644 index 000000000000000..d2cf56d26075c8e --- /dev/null +++ b/x-pack/plugins/fleet/server/saved_objects/migrations/security_solution/to_v8_10_0.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SavedObjectUnsanitizedDoc } from '@kbn/core/server'; + +import type { SavedObjectModelDataBackfillFn } from '@kbn/core-saved-objects-server'; + +import { omit } from 'lodash'; + +import type { SavedObjectModelVersionForwardCompatibilityFn } from '@kbn/core-saved-objects-server'; + +import type { PackagePolicy } from '../../../../common'; + +export const migratePackagePolicyToV8100: SavedObjectModelDataBackfillFn< + PackagePolicy, + PackagePolicy +> = (packagePolicyDoc) => { + if (packagePolicyDoc.attributes.package?.name !== 'endpoint') { + return { attributes: packagePolicyDoc.attributes }; + } + + const updatedPackagePolicyDoc: SavedObjectUnsanitizedDoc = packagePolicyDoc; + + const input = updatedPackagePolicyDoc.attributes.inputs[0]; + + if (input && input.config) { + const policy = input.config.policy.value; + + policy.windows.behavior_protection.reputation_service = false; + policy.mac.behavior_protection.reputation_service = false; + policy.linux.behavior_protection.reputation_service = false; + } + + return { + attributes: { + inputs: updatedPackagePolicyDoc.attributes.inputs, + }, + }; +}; + +export const migratePackagePolicyEvictionsFromV8100: SavedObjectModelVersionForwardCompatibilityFn = + (unknownAttributes) => { + const attributes = unknownAttributes as PackagePolicy; + if (attributes.package?.name !== 'endpoint') { + return attributes; + } + + const updatedAttributes = attributes; + + const input = updatedAttributes.inputs[0]; + + if (input && input.config) { + const policy = input.config.policy.value; + + policy.windows.behavior_protection = omit(policy.windows.behavior_protection, [ + 'reputation_service', + ]); + policy.linux.behavior_protection = omit(policy.linux.behavior_protection, [ + 'reputation_service', + ]); + policy.mac.behavior_protection = omit(policy.mac.behavior_protection, ['reputation_service']); + } + + return updatedAttributes; + }; diff --git a/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts b/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts index 06c7eda0785a72e..fab5a165ad47d20 100644 --- a/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts +++ b/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts @@ -42,6 +42,7 @@ export const policyFactory = (license = '', cloud = false): PolicyConfig => { }, behavior_protection: { mode: ProtectionModes.prevent, + reputation_service: false, supported: true, }, popup: { @@ -86,6 +87,7 @@ export const policyFactory = (license = '', cloud = false): PolicyConfig => { }, behavior_protection: { mode: ProtectionModes.prevent, + reputation_service: false, supported: true, }, memory_protection: { @@ -127,6 +129,7 @@ export const policyFactory = (license = '', cloud = false): PolicyConfig => { }, behavior_protection: { mode: ProtectionModes.prevent, + reputation_service: false, supported: true, }, memory_protection: { @@ -200,6 +203,7 @@ export const policyFactoryWithoutPaidFeatures = ( }, behavior_protection: { mode: ProtectionModes.off, + reputation_service: false, supported: false, }, attack_surface_reduction: { @@ -231,6 +235,7 @@ export const policyFactoryWithoutPaidFeatures = ( ...policy.mac, behavior_protection: { mode: ProtectionModes.off, + reputation_service: false, supported: false, }, memory_protection: { @@ -257,6 +262,7 @@ export const policyFactoryWithoutPaidFeatures = ( ...policy.linux, behavior_protection: { mode: ProtectionModes.off, + reputation_service: false, supported: false, }, memory_protection: { diff --git a/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.test.ts b/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.test.ts index c59844f70ead928..e6e8efc21ee2529 100644 --- a/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.test.ts @@ -24,23 +24,29 @@ describe('Policy Config helpers', () => { supported: false, }; + const notSupportedBehaviorProtection: PolicyConfig['windows']['behavior_protection'] = { + mode: ProtectionModes.off, + supported: false, + reputation_service: false, + }; + const inputPolicyWithoutSupportedProtections: PolicyConfig = { ...defaultPolicy, windows: { ...defaultPolicy.windows, memory_protection: notSupported, - behavior_protection: notSupported, + behavior_protection: notSupportedBehaviorProtection, ransomware: notSupported, }, mac: { ...defaultPolicy.mac, memory_protection: notSupported, - behavior_protection: notSupported, + behavior_protection: notSupportedBehaviorProtection, }, linux: { ...defaultPolicy.linux, memory_protection: notSupported, - behavior_protection: notSupported, + behavior_protection: notSupportedBehaviorProtection, }, }; @@ -49,18 +55,18 @@ describe('Policy Config helpers', () => { windows: { ...eventsOnlyPolicy.windows, memory_protection: notSupported, - behavior_protection: notSupported, + behavior_protection: notSupportedBehaviorProtection, ransomware: notSupported, }, mac: { ...eventsOnlyPolicy.mac, memory_protection: notSupported, - behavior_protection: notSupported, + behavior_protection: notSupportedBehaviorProtection, }, linux: { ...eventsOnlyPolicy.linux, memory_protection: notSupported, - behavior_protection: notSupported, + behavior_protection: notSupportedBehaviorProtection, }, }; @@ -134,7 +140,7 @@ export const eventsOnlyPolicy: PolicyConfig = { malware: { mode: ProtectionModes.off, blocklist: false }, ransomware: { mode: ProtectionModes.off, supported: true }, memory_protection: { mode: ProtectionModes.off, supported: true }, - behavior_protection: { mode: ProtectionModes.off, supported: true }, + behavior_protection: { mode: ProtectionModes.off, supported: true, reputation_service: false }, popup: { malware: { message: '', enabled: false }, ransomware: { message: '', enabled: false }, @@ -148,7 +154,7 @@ export const eventsOnlyPolicy: PolicyConfig = { mac: { events: { process: true, file: true, network: true }, malware: { mode: ProtectionModes.off, blocklist: false }, - behavior_protection: { mode: ProtectionModes.off, supported: true }, + behavior_protection: { mode: ProtectionModes.off, supported: true, reputation_service: false }, memory_protection: { mode: ProtectionModes.off, supported: true }, popup: { malware: { message: '', enabled: false }, @@ -169,7 +175,7 @@ export const eventsOnlyPolicy: PolicyConfig = { tty_io: false, }, malware: { mode: ProtectionModes.off, blocklist: false }, - behavior_protection: { mode: ProtectionModes.off, supported: true }, + behavior_protection: { mode: ProtectionModes.off, supported: true, reputation_service: false }, memory_protection: { mode: ProtectionModes.off, supported: true }, popup: { malware: { message: '', enabled: false }, diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 3e48770cd5b3970..d3359e8389aae01 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -967,7 +967,7 @@ export interface PolicyConfig { }; malware: ProtectionFields & BlocklistFields; memory_protection: ProtectionFields & SupportedFields; - behavior_protection: ProtectionFields & SupportedFields; + behavior_protection: BehaviorProtectionFields & SupportedFields; ransomware: ProtectionFields & SupportedFields; logging: { file: string; @@ -1007,7 +1007,7 @@ export interface PolicyConfig { network: boolean; }; malware: ProtectionFields & BlocklistFields; - behavior_protection: ProtectionFields & SupportedFields; + behavior_protection: BehaviorProtectionFields & SupportedFields; memory_protection: ProtectionFields & SupportedFields; popup: { malware: { @@ -1037,7 +1037,7 @@ export interface PolicyConfig { tty_io: boolean; }; malware: ProtectionFields & BlocklistFields; - behavior_protection: ProtectionFields & SupportedFields; + behavior_protection: BehaviorProtectionFields & SupportedFields; memory_protection: ProtectionFields & SupportedFields; popup: { malware: { @@ -1099,6 +1099,10 @@ export interface ProtectionFields { mode: ProtectionModes; } +export interface BehaviorProtectionFields extends ProtectionFields { + reputation_service: boolean; +} + /** Policy: Supported fields */ export interface SupportedFields { supported: boolean; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts index d2876f1bcdd248e..f73242f036c902c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts @@ -283,7 +283,11 @@ describe('policy details: ', () => { }, malware: { mode: 'prevent', blocklist: true }, memory_protection: { mode: 'off', supported: false }, - behavior_protection: { mode: 'off', supported: false }, + behavior_protection: { + mode: 'off', + supported: false, + reputation_service: false, + }, ransomware: { mode: 'off', supported: false }, attack_surface_reduction: { credential_hardening: { @@ -316,7 +320,11 @@ describe('policy details: ', () => { mac: { events: { process: true, file: true, network: true }, malware: { mode: 'prevent', blocklist: true }, - behavior_protection: { mode: 'off', supported: false }, + behavior_protection: { + mode: 'off', + supported: false, + reputation_service: false, + }, memory_protection: { mode: 'off', supported: false }, popup: { malware: { @@ -348,7 +356,11 @@ describe('policy details: ', () => { }, logging: { file: 'info' }, malware: { mode: 'prevent', blocklist: true }, - behavior_protection: { mode: 'off', supported: false }, + behavior_protection: { + mode: 'off', + supported: false, + reputation_service: false, + }, memory_protection: { mode: 'off', supported: false }, popup: { malware: { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/behaviour_protection_card.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/behaviour_protection_card.test.tsx index 949c84324f7aab6..3eeee6db3d62297 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/behaviour_protection_card.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/behaviour_protection_card.test.tsx @@ -10,13 +10,16 @@ import type { AppContextTestRender } from '../../../../../../../common/mock/endp import { createAppRootMockRenderer } from '../../../../../../../common/mock/endpoint'; import { FleetPackagePolicyGenerator } from '../../../../../../../../common/endpoint/data_generators/fleet_package_policy_generator'; import React from 'react'; -import type { BehaviourProtectionCardProps } from './behaviour_protection_card'; -import { BehaviourProtectionCard, LOCKED_CARD_BEHAVIOR_TITLE } from './behaviour_protection_card'; import { licenseService as licenseServiceMocked } from '../../../../../../../common/hooks/__mocks__/use_license'; import { useLicense as _useLicense } from '../../../../../../../common/hooks/use_license'; import { createLicenseServiceMock } from '../../../../../../../../common/license/mocks'; import { set } from 'lodash'; import { ProtectionModes } from '../../../../../../../../common/endpoint/types'; +import type { BehaviourProtectionCardProps } from './protection_seetings_card/behaviour_protection_card'; +import { + BehaviourProtectionCard, + LOCKED_CARD_BEHAVIOR_TITLE, +} from './protection_seetings_card/behaviour_protection_card'; jest.mock('../../../../../../../common/hooks/use_license'); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/behaviour_protection_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/protection_seetings_card/behaviour_protection_card.tsx similarity index 72% rename from x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/behaviour_protection_card.tsx rename to x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/protection_seetings_card/behaviour_protection_card.tsx index 1a71e384146c443..1a4a37f9d5c81fb 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/behaviour_protection_card.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/protection_seetings_card/behaviour_protection_card.tsx @@ -9,18 +9,19 @@ import React, { memo } from 'react'; import { i18n } from '@kbn/i18n'; import { OperatingSystem } from '@kbn/securitysolution-utils'; import { EuiSpacer } from '@elastic/eui'; -import { useTestIdGenerator } from '../../../../../../hooks/use_test_id_generator'; -import { SettingCard } from '../setting_card'; -import { NotifyUserOption } from '../notify_user_option'; -import { DetectPreventProtectionLevel } from '../detect_prevent_protection_level'; -import { ProtectionSettingCardSwitch } from '../protection_setting_card_switch'; -import type { Immutable } from '../../../../../../../../common/endpoint/types'; -import { PolicyOperatingSystem } from '../../../../../../../../common/endpoint/types'; -import type { BehaviorProtectionOSes } from '../../../../types'; -import { useLicense } from '../../../../../../../common/hooks/use_license'; -import { SettingLockedCard } from '../setting_locked_card'; -import type { PolicyFormComponentCommonProps } from '../../types'; -import { RelatedDetectionRulesCallout } from '../related_detection_rules_callout'; +import { RelatedDetectionRulesCallout } from '../../related_detection_rules_callout'; +import { ReputationService } from './components/reputation_service'; +import { useTestIdGenerator } from '../../../../../../../hooks/use_test_id_generator'; +import { SettingCard } from '../../setting_card'; +import { NotifyUserOption } from '../../notify_user_option'; +import { DetectPreventProtectionLevel } from '../../detect_prevent_protection_level'; +import { ProtectionSettingCardSwitch } from '../../protection_setting_card_switch'; +import type { Immutable } from '../../../../../../../../../common/endpoint/types'; +import { PolicyOperatingSystem } from '../../../../../../../../../common/endpoint/types'; +import type { BehaviorProtectionOSes } from '../../../../../types'; +import { useLicense } from '../../../../../../../../common/hooks/use_license'; +import { SettingLockedCard } from '../../setting_locked_card'; +import type { PolicyFormComponentCommonProps } from '../../../types'; export const LOCKED_CARD_BEHAVIOR_TITLE = i18n.translate( 'xpack.securitySolution.endpoint.policy.details.behavior', @@ -86,6 +87,13 @@ export const BehaviourProtectionCard = memo( data-test-subj={getTestId('protectionLevel')} /> + + { + const isEditMode = mode === 'edit'; + + const { cloud } = useKibana().services; + const isCloud = cloud?.isCloudEnabled ?? false; + + const getTestId = useTestIdGenerator(dataTestSubj); + + const protectionTurnedOn = policy.windows.behavior_protection.mode !== ProtectionModes.off; + + const checkboxChecked = + policy.windows.behavior_protection.reputation_service && protectionTurnedOn; + + const handleChange = useCallback( + (event) => { + const newPayload = cloneDeep(policy); + newPayload.windows.behavior_protection.reputation_service = event.target.checked; + newPayload.mac.behavior_protection.reputation_service = event.target.checked; + newPayload.linux.behavior_protection.reputation_service = event.target.checked; + + onChange({ isValid: true, updatedPolicy: newPayload }); + }, + [policy, onChange] + ); + + const checkboxLabel = checkboxChecked + ? USE_REPUTATION_SERVICE_CHECKBOX_LABEL + : DO_NOT_USE_REPUTATION_SERVICE_CHECKBOX_LABEL; + + if (!isCloud) { + return null; + } + + return ( +
+ + + + + +

+ +

+
+
+ + + } + /> + +
+
+ + {isEditMode ? ( + + ) : ( + <>{checkboxLabel} + )} +
+ ); + } +); + +ReputationService.displayName = 'ReputationService'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.tsx index b55fbeba172baea..32dfebbfb46f395 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.tsx @@ -84,6 +84,11 @@ export const ProtectionSettingCardSwitch = React.memo( newPayload[os].popup[protection as LinuxPolicyProtection].enabled = event.target.checked; } + if (protection === 'behavior_protection') { + newPayload.windows.behavior_protection.reputation_service = false; + newPayload.mac.behavior_protection.reputation_service = false; + newPayload.linux.behavior_protection.reputation_service = false; + } } } } else { @@ -96,6 +101,11 @@ export const ProtectionSettingCardSwitch = React.memo( newPayload[os][protection as LinuxPolicyProtection].mode = ProtectionModes.prevent; } if (isPlatinumPlus) { + if (protection === 'behavior_protection') { + newPayload.windows.behavior_protection.reputation_service = false; + newPayload.mac.behavior_protection.reputation_service = false; + newPayload.linux.behavior_protection.reputation_service = false; + } if (os === 'windows') { newPayload[os].popup[protection].enabled = event.target.checked; } else if (os === 'mac') { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.tsx index 8771e40e4be7c35..623c61ebbf0ee0d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.tsx @@ -13,7 +13,7 @@ import { LinuxEventCollectionCard } from './components/cards/linux_event_collect import { MacEventCollectionCard } from './components/cards/mac_event_collection_card'; import { WindowsEventCollectionCard } from './components/cards/windows_event_collection_card'; import { AttackSurfaceReductionCard } from './components/cards/attack_surface_reduction_card'; -import { BehaviourProtectionCard } from './components/cards/behaviour_protection_card'; +import { BehaviourProtectionCard } from './components/cards/protection_seetings_card/behaviour_protection_card'; import { MemoryProtectionCard } from './components/cards/memory_protection_card'; import { RansomwareProtectionCard } from './components/cards/ransomware_protection_card'; import { MalwareProtectionsCard } from './components/cards/malware_protections_card'; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts index 867876d6345a3a2..58dcd24bdf916af 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts @@ -49,9 +49,14 @@ describe('Create Default Policy tests ', () => { // check some of the protections to be disabled const disabledButSupported = { mode: ProtectionModes.off, supported: true }; - expect(policy.windows.behavior_protection).toEqual(disabledButSupported); + const disabledButSupportedBehaviorProtection = { + mode: ProtectionModes.off, + supported: true, + reputation_service: false, + }; + expect(policy.windows.behavior_protection).toEqual(disabledButSupportedBehaviorProtection); expect(policy.mac.memory_protection).toEqual(disabledButSupported); - expect(policy.linux.behavior_protection).toEqual(disabledButSupported); + expect(policy.linux.behavior_protection).toEqual(disabledButSupportedBehaviorProtection); // malware popups should be disabled expect(policy.windows.popup.malware.enabled).toBeFalsy(); @@ -72,9 +77,14 @@ describe('Create Default Policy tests ', () => { // check some of the protections to be disabled and unsupported const disabledAndUnsupported = { mode: ProtectionModes.off, supported: false }; - expect(policy.windows.behavior_protection).toEqual(disabledAndUnsupported); + const disabledAndUnsupportedBehaviorProtection = { + mode: ProtectionModes.off, + supported: false, + reputation_service: false, + }; + expect(policy.windows.behavior_protection).toEqual(disabledAndUnsupportedBehaviorProtection); expect(policy.mac.memory_protection).toEqual(disabledAndUnsupported); - expect(policy.linux.behavior_protection).toEqual(disabledAndUnsupported); + expect(policy.linux.behavior_protection).toEqual(disabledAndUnsupportedBehaviorProtection); // malware popups are enabled on unpaid license expect(policy.windows.popup.malware.enabled).toBeTruthy(); @@ -130,9 +140,14 @@ describe('Create Default Policy tests ', () => { // check some of the protections to be disabled const disabledButSupported = { mode: ProtectionModes.off, supported: true }; - expect(policy.windows.behavior_protection).toEqual(disabledButSupported); + const disabledButSupportedBehaviorProtection = { + mode: ProtectionModes.off, + supported: true, + reputation_service: false, + }; + expect(policy.windows.behavior_protection).toEqual(disabledButSupportedBehaviorProtection); expect(policy.mac.memory_protection).toEqual(disabledButSupported); - expect(policy.linux.behavior_protection).toEqual(disabledButSupported); + expect(policy.linux.behavior_protection).toEqual(disabledButSupportedBehaviorProtection); // malware popups should be disabled expect(policy.windows.popup.malware.enabled).toBeFalsy(); From 181eb39b70df8d4968a213fd133a3cef503e19f1 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Tue, 25 Jul 2023 01:55:23 -0700 Subject: [PATCH 07/29] [Security Solution][Feat] Integrate Discover Tab in timeline (#160036) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary First step for https://github.com/elastic/security-team/issues/6677 Aim of this PR is embed Discover in Security Solution. Discover must be embedded as a complete app with certain set of capabilities working. The set capabilities that need to working are listed here : https://github.com/elastic/security-team/issues/6673 Release notes should be based on https://github.com/elastic/security-team/issues/6673 ### ⚠️ Note - These changes are only available in serverless mode of security solution behind a feature-flag called `discoverInTimeline`. Adds below options to `serverless.security.yml`: ```yaml # Serverless security specific options xpack.securitySolution.enableExperimental: - discoverInTimeline ``` You can use below command to run serverless instance of security solution : ```bash yarn serverless-security ``` This Implements following changes for each plugin. ### Discover 1. Exports Discover App as Lazy component. 2. Ability to override Discover Services. 3. Adds a parameter `mode` which switches off/on certain options based on the `mode`. `Mode` has possible values of `embedded` and `standalone`. For example, `embedded` switches off Discover breadcrumb syncing, because consuming app may not need it. ### Unified Search 1. Ability to export a Search bar with custom depedency instances. 2. For example, today Unified Search uses a singleton global `dataService` which store global KQL filters and queries. This customization, let consumers of unified search to pass a new instance of `dataService`. 4. Please see below diagram for more clarity. ### Navigation 1. Ability to export a custom stateful TopNav Menu which includes: - DataView picker - KQL Search Bar - TimeRange Selector 2. Currently navigation consumes an instance of unified service which uses a global singleton `data` service. 3. This PR creates a new instance of unified search which is then passed to navigation to get a custom instance of `TopNav` Menu. ### Security Solution 1. Imports Discover Container Component 2. Uses customization point to pass a custom query bar. 3. Implements Custom KQL Query Bar with below customizations ![image](https://github.com/elastic/kibana/assets/7485038/5313c108-0976-4a00-80b7-d03b9f69d15c) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Davis McPhee --- config/serverless.security.yml | 5 + .../top_nav/discover_topnav.test.tsx | 58 ++++++-- .../components/top_nav/discover_topnav.tsx | 7 +- .../application/main/discover_main_app.tsx | 16 ++- .../application/main/discover_main_route.tsx | 37 ++++-- .../discover/public/application/types.ts | 2 + .../discover_container.test.tsx | 93 +++++++++++++ .../discover_container/discover_container.tsx | 95 +++++++++++++ .../components/discover_container/index.ts | 18 +++ .../search_bar_customization.ts | 5 +- src/plugins/discover/public/index.ts | 1 + .../discover/public/{mocks.ts => mocks.tsx} | 2 + src/plugins/discover/public/plugin.tsx | 67 ++++++---- src/plugins/discover/tsconfig.json | 14 +- src/plugins/navigation/public/mocks.ts | 1 + src/plugins/navigation/public/plugin.ts | 23 ++++ src/plugins/navigation/public/types.ts | 7 +- src/plugins/unified_search/public/index.ts | 1 + .../unified_search/public/mocks/mocks.ts | 1 + src/plugins/unified_search/public/plugin.ts | 34 +++-- .../public/search_bar/create_search_bar.tsx | 2 +- src/plugins/unified_search/public/types.ts | 10 +- .../common/experimental_features.ts | 6 + .../common/types/timeline/index.ts | 1 + .../entity_analytics_management_page.cy.ts | 5 +- .../cypress/screens/alerts.ts | 3 +- .../cypress/screens/date_picker.ts | 15 ++- .../screens/entity_analytics_management.ts | 4 + .../cypress/screens/search_bar.ts | 9 +- .../cypress/screens/security_header.ts | 6 +- .../cypress/screens/timeline.ts | 3 +- .../cypress/tasks/date_picker.ts | 14 +- .../cypress/tasks/search_bar.ts | 6 +- x-pack/plugins/security_solution/kibana.jsonc | 15 ++- .../common/lib/kibana/kibana_react.mock.ts | 8 ++ .../components/risk_score_preview_section.tsx | 2 +- .../public/management/cypress/tasks/alerts.ts | 6 +- .../security_solution/public/plugin.tsx | 31 +++++ .../components/flyout/pane/index.test.tsx | 1 + .../discover_tab_content/index.test.tsx | 29 ++++ .../timeline/discover_tab_content/index.tsx | 71 ++++++++++ .../use_get_stateful_query_bar.test.tsx | 21 +++ .../use_get_stateful_query_bar.tsx | 47 +++++++ .../timeline/tabs_content/index.tsx | 125 ++++++++---------- .../timeline/tabs_content/translations.ts | 7 + .../plugins/security_solution/public/types.ts | 10 +- .../plugins/security_solution/tsconfig.json | 3 + 47 files changed, 767 insertions(+), 180 deletions(-) create mode 100644 src/plugins/discover/public/components/discover_container/discover_container.test.tsx create mode 100644 src/plugins/discover/public/components/discover_container/discover_container.tsx create mode 100644 src/plugins/discover/public/components/discover_container/index.ts rename src/plugins/discover/public/{mocks.ts => mocks.tsx} (91%) create mode 100644 x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/index.tsx create mode 100644 x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/use_get_stateful_query_bar.test.tsx create mode 100644 x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/use_get_stateful_query_bar.tsx diff --git a/config/serverless.security.yml b/config/serverless.security.yml index bad71f38f24af9a..ede91b167dd054e 100644 --- a/config/serverless.security.yml +++ b/config/serverless.security.yml @@ -22,3 +22,8 @@ xpack.serverless.plugin.developer.projectSwitcher.currentType: 'security' # Specify in telemetry the project type telemetry.labels.serverless: security + +# Serverless security specific options +xpack.securitySolution.enableExperimental: + - discoverInTimeline + diff --git a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.test.tsx b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.test.tsx index ada23ff7f8f5568..9f16c7e77bfa475 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.test.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.test.tsx @@ -19,6 +19,7 @@ import { DiscoverMainProvider } from '../../services/discover_state_provider'; import type { SearchBarCustomization, TopNavCustomization } from '../../../../customizations'; import type { DiscoverCustomizationId } from '../../../../customizations/customization_service'; +import { useDiscoverCustomization } from '../../../../customizations'; setHeaderActionMenuMounter(jest.fn()); jest.mock('@kbn/kibana-react-plugin/public', () => ({ @@ -28,6 +29,9 @@ jest.mock('@kbn/kibana-react-plugin/public', () => ({ }), })); +const MockCustomSearchBar: typeof mockDiscoverService.navigation.ui.AggregateQueryTopNavMenu = + () =>
; + const mockTopNavCustomization: TopNavCustomization = { id: 'top_nav', }; @@ -37,24 +41,16 @@ const mockSearchBarCustomization: SearchBarCustomization = { CustomDataViewPicker: jest.fn(() =>
), }; +const mockSearchBarCustomizationWithCustomSearchBar: SearchBarCustomization = { + id: 'search_bar', + CustomSearchBar: MockCustomSearchBar, +}; + let mockUseCustomizations = false; jest.mock('../../../../customizations', () => ({ ...jest.requireActual('../../../../customizations'), - useDiscoverCustomization: jest.fn((id: DiscoverCustomizationId) => { - if (!mockUseCustomizations) { - return undefined; - } - - switch (id) { - case 'top_nav': - return mockTopNavCustomization; - case 'search_bar': - return mockSearchBarCustomization; - default: - throw new Error(`Unknown customization id: ${id}`); - } - }), + useDiscoverCustomization: jest.fn(), })); function getProps(savePermissions = true): DiscoverTopNavProps { @@ -79,6 +75,23 @@ describe('Discover topnav component', () => { mockTopNavCustomization.getMenuItems = undefined; mockUseCustomizations = false; jest.clearAllMocks(); + + (useDiscoverCustomization as jest.Mock).mockImplementation( + jest.fn((id: DiscoverCustomizationId) => { + if (!mockUseCustomizations) { + return undefined; + } + + switch (id) { + case 'top_nav': + return mockTopNavCustomization; + case 'search_bar': + return mockSearchBarCustomization; + default: + throw new Error(`Unknown customization id: ${id}`); + } + }) + ); }); test('generated config of TopNavMenu config is correct when discover save permissions are assigned', () => { @@ -175,6 +188,23 @@ describe('Discover topnav component', () => { }); describe('search bar customization', () => { + it('should render custom Search Bar', () => { + (useDiscoverCustomization as jest.Mock).mockImplementation((id: DiscoverCustomizationId) => { + if (id === 'search_bar') { + return mockSearchBarCustomizationWithCustomSearchBar; + } + }); + + const props = getProps(); + const component = mountWithIntl( + + + + ); + + expect(component.find({ 'data-test-subj': 'custom-search-bar' })).toHaveLength(1); + }); + it('should render CustomDataViewPicker', () => { mockUseCustomizations = true; const props = getProps(); diff --git a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx index 528343ab8c260ba..d54e6490da4d15b 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx @@ -201,8 +201,13 @@ export const DiscoverTopNav = ({ const searchBarCustomization = useDiscoverCustomization('search_bar'); + const SearchBar = useMemo( + () => searchBarCustomization?.CustomSearchBar ?? AggregateQueryTopNavMenu, + [searchBarCustomization?.CustomSearchBar, AggregateQueryTopNavMenu] + ); + return ( - { - const pageTitleSuffix = savedSearch.id && savedSearch.title ? `: ${savedSearch.title}` : ''; - chrome.docTitle.change(`Discover${pageTitleSuffix}`); - setBreadcrumbsTitle({ title: savedSearch.title, services }); - }, [chrome.docTitle, savedSearch.id, savedSearch.title, services]); + if (mode === 'standalone') { + const pageTitleSuffix = savedSearch.id && savedSearch.title ? `: ${savedSearch.title}` : ''; + chrome.docTitle.change(`Discover${pageTitleSuffix}`); + setBreadcrumbsTitle({ title: savedSearch.title, services }); + } + }, [mode, chrome.docTitle, savedSearch.id, savedSearch.title, services]); useEffect(() => { addHelpMenuToAppChrome(chrome, docLinks); diff --git a/src/plugins/discover/public/application/main/discover_main_route.tsx b/src/plugins/discover/public/application/main/discover_main_route.tsx index ae90d0b3dc736dc..39726044a250222 100644 --- a/src/plugins/discover/public/application/main/discover_main_route.tsx +++ b/src/plugins/discover/public/application/main/discover_main_route.tsx @@ -34,6 +34,7 @@ import { DiscoverCustomizationProvider, useDiscoverCustomizationService, } from '../../customizations'; +import type { DiscoverDisplayMode } from '../types'; const DiscoverMainAppMemoized = memo(DiscoverMainApp); @@ -44,9 +45,14 @@ interface DiscoverLandingParams { export interface MainRouteProps { customizationCallbacks: CustomizationCallback[]; isDev: boolean; + mode?: DiscoverDisplayMode; } -export function DiscoverMainRoute({ customizationCallbacks, isDev }: MainRouteProps) { +export function DiscoverMainRoute({ + customizationCallbacks, + isDev, + mode = 'standalone', +}: MainRouteProps) { const history = useHistory(); const services = useDiscoverServices(); const { @@ -146,21 +152,21 @@ export function DiscoverMainRoute({ customizationCallbacks, isDev }: MainRoutePr dataView: nextDataView, dataViewSpec: historyLocationState?.dataViewSpec, }); + if (mode === 'standalone') { + if (currentSavedSearch?.id) { + chrome.recentlyAccessed.add( + getSavedSearchFullPathUrl(currentSavedSearch.id), + currentSavedSearch.title ?? '', + currentSavedSearch.id + ); + } - if (currentSavedSearch?.id) { - chrome.recentlyAccessed.add( - getSavedSearchFullPathUrl(currentSavedSearch.id), - currentSavedSearch.title ?? '', - currentSavedSearch.id + chrome.setBreadcrumbs( + currentSavedSearch && currentSavedSearch.title + ? getSavedSearchBreadcrumbs({ id: currentSavedSearch.title, services }) + : getRootBreadcrumbs({ services }) ); } - - chrome.setBreadcrumbs( - currentSavedSearch && currentSavedSearch.title - ? getSavedSearchBreadcrumbs({ id: currentSavedSearch.title, services }) - : getRootBreadcrumbs({ services }) - ); - setLoading(false); if (services.analytics) { const loadSavedSearchDuration = window.performance.now() - loadSavedSearchStartTime; @@ -205,6 +211,7 @@ export function DiscoverMainRoute({ customizationCallbacks, isDev }: MainRoutePr core.theme, basePath, toastNotifications, + mode, ] ); @@ -278,8 +285,10 @@ export function DiscoverMainRoute({ customizationCallbacks, isDev }: MainRoutePr return ( - + ); } +// eslint-disable-next-line import/no-default-export +export default DiscoverMainRoute; diff --git a/src/plugins/discover/public/application/types.ts b/src/plugins/discover/public/application/types.ts index 798e0f350cc5f51..588ca00f8982560 100644 --- a/src/plugins/discover/public/application/types.ts +++ b/src/plugins/discover/public/application/types.ts @@ -13,3 +13,5 @@ export enum FetchStatus { COMPLETE = 'complete', ERROR = 'error', } + +export type DiscoverDisplayMode = 'embedded' | 'standalone'; diff --git a/src/plugins/discover/public/components/discover_container/discover_container.test.tsx b/src/plugins/discover/public/components/discover_container/discover_container.test.tsx new file mode 100644 index 000000000000000..3fb0e5d6bb43536 --- /dev/null +++ b/src/plugins/discover/public/components/discover_container/discover_container.test.tsx @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { render, waitFor } from '@testing-library/react'; +import { DiscoverServices } from '../../build_services'; +import DiscoverContainerInternal, { DiscoverContainerInternalProps } from './discover_container'; +import { ScopedHistory } from '@kbn/core-application-browser'; +import { discoverServiceMock } from '../../__mocks__/services'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; + +const mockOverrideService = {}; +const getDiscoverServicesMock = jest.fn( + () => new Promise((resolve) => resolve(discoverServiceMock)) +); + +jest.mock('../../application/main', () => { + return { + DiscoverMainRoute: () => <>, + }; +}); + +jest.mock('@kbn/kibana-react-plugin/public'); + +const { history } = discoverServiceMock; + +const customizeMock = jest.fn(); + +const TestComponent = (props: Partial) => { + return ( + )} + getDiscoverServices={getDiscoverServicesMock} + /> + ); +}; + +const TEST_IDS = { + DISCOVER_CONTAINER_INTERNAL: 'data-container-internal-wrapper', +}; + +describe('DiscoverContainerInternal should render properly', () => { + beforeAll(() => { + (KibanaContextProvider as jest.Mock).mockImplementation(() => <>); + }); + + afterEach(() => jest.clearAllMocks()); + + it('should render', async () => { + const { getByTestId, queryByTestId } = render(); + expect(queryByTestId(TEST_IDS.DISCOVER_CONTAINER_INTERNAL)).not.toBeInTheDocument(); + + expect(getDiscoverServicesMock).toHaveBeenCalledTimes(1); + + await waitFor(() => { + expect(getByTestId(TEST_IDS.DISCOVER_CONTAINER_INTERNAL)).toBeInTheDocument(); + }); + }); + + it('should render with overrideServices', async () => { + const overrideServices: Partial = { + data: { + ...dataPluginMock.createStartContract(), + // @ts-expect-error + _name: 'custom', + }, + }; + render(); + + await waitFor(() => { + expect(KibanaContextProvider as jest.Mock).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + services: expect.objectContaining({ + data: expect.objectContaining({ + _name: 'custom', + }), + }), + }), + {} + ); + }); + }); +}); diff --git a/src/plugins/discover/public/components/discover_container/discover_container.tsx b/src/plugins/discover/public/components/discover_container/discover_container.tsx new file mode 100644 index 000000000000000..23afbd7965bc716 --- /dev/null +++ b/src/plugins/discover/public/components/discover_container/discover_container.tsx @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import type { ScopedHistory } from '@kbn/core/public'; +import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import React, { useEffect, useMemo, useState } from 'react'; +import { DiscoverMainRoute } from '../../application/main'; +import type { DiscoverServices } from '../../build_services'; +import type { CustomizationCallback } from '../../customizations'; +import { setHeaderActionMenuMounter, setScopedHistory } from '../../kibana_services'; +import { LoadingIndicator } from '../common/loading_indicator'; + +export interface DiscoverContainerInternalProps { + /* + * Any override that user of this hook + * wants discover to use. Need to keep in mind that this + * param is only for overrides for the services that Discover + * already consumes. + */ + overrideServices: Partial; + getDiscoverServices: () => Promise; + scopedHistory: ScopedHistory; + customize: CustomizationCallback; + isDev: boolean; +} + +const DiscoverContainerWrapper = euiStyled(EuiFlexGroup)` + width: 100%; + height: 100%; + + // override the embedded discover page height + // to fit in the container + .dscPage { + height: 100% +} +`; + +export const DiscoverContainerInternal = ({ + overrideServices, + scopedHistory, + customize, + isDev, + getDiscoverServices, +}: DiscoverContainerInternalProps) => { + const [discoverServices, setDiscoverServices] = useState(); + const customizationCallbacks = useMemo(() => [customize], [customize]); + const [initialized, setInitialized] = useState(false); + + useEffect(() => { + getDiscoverServices().then((svcs) => setDiscoverServices(svcs)); + }, [getDiscoverServices]); + + useEffect(() => { + setScopedHistory(scopedHistory); + setHeaderActionMenuMounter(() => {}); + setInitialized(true); + }, [scopedHistory]); + + const services = useMemo(() => { + if (!discoverServices) return; + return { ...discoverServices, ...overrideServices }; + }, [discoverServices, overrideServices]); + + if (!initialized || !services) { + return ( + + + + ); + } + + return ( + + + + + + + + ); +}; + +// eslint-disable-next-line import/no-default-export +export default DiscoverContainerInternal; diff --git a/src/plugins/discover/public/components/discover_container/index.ts b/src/plugins/discover/public/components/discover_container/index.ts new file mode 100644 index 000000000000000..0cc48d01dfafbc3 --- /dev/null +++ b/src/plugins/discover/public/components/discover_container/index.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 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 { withSuspense } from '@kbn/shared-ux-utility'; +import { lazy } from 'react'; +import type { DiscoverContainerInternalProps } from './discover_container'; + +export type DiscoverContainerProps = Omit< + DiscoverContainerInternalProps, + 'isDev' | 'getDiscoverServices' +>; + +export const DiscoverContainerInternal = withSuspense(lazy(() => import('./discover_container'))); diff --git a/src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts b/src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts index 8117781a95c9325..4395d310aa99785 100644 --- a/src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts +++ b/src/plugins/discover/public/customizations/customization_types/search_bar_customization.ts @@ -6,9 +6,12 @@ * Side Public License, v 1. */ -import type { ComponentType } from 'react'; +import type { AggregateQuery } from '@kbn/es-query'; +import type { TopNavMenuProps } from '@kbn/navigation-plugin/public'; +import type { ComponentType, ReactElement } from 'react'; export interface SearchBarCustomization { id: 'search_bar'; CustomDataViewPicker?: ComponentType; + CustomSearchBar?: (props: TopNavMenuProps) => ReactElement; } diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts index dba5a81bee1e3c4..f567380276354eb 100644 --- a/src/plugins/discover/public/index.ts +++ b/src/plugins/discover/public/index.ts @@ -16,6 +16,7 @@ export function plugin(initializerContext: PluginInitializerContext) { export type { ISearchEmbeddable, SearchInput } from './embeddable'; export type { DiscoverStateContainer } from './application/main/services/discover_state'; +export type { DiscoverContainerProps } from './components/discover_container'; export type { CustomizationCallback, DiscoverProfileId, diff --git a/src/plugins/discover/public/mocks.ts b/src/plugins/discover/public/mocks.tsx similarity index 91% rename from src/plugins/discover/public/mocks.ts rename to src/plugins/discover/public/mocks.tsx index 93d4202ff3f3e67..e733e9d32dbeef9 100644 --- a/src/plugins/discover/public/mocks.ts +++ b/src/plugins/discover/public/mocks.tsx @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import React from 'react'; import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; import { DiscoverSetup, DiscoverStart } from '.'; @@ -25,6 +26,7 @@ const createSetupContract = (): Setup => { const createStartContract = (): Start => { const startContract: Start = { locator: sharePluginMock.createLocator(), + DiscoverContainer: jest.fn().mockImplementation(() => <>), registerCustomizationProfile: jest.fn(), }; return startContract; diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index c7f2dcdd0c36bf9..41d3ba10f9b2dbf 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -7,7 +7,7 @@ */ import { i18n } from '@kbn/i18n'; -import React from 'react'; +import React, { ComponentType } from 'react'; import { BehaviorSubject, combineLatest, map } from 'rxjs'; import { AppMountParameters, @@ -78,6 +78,7 @@ import { createProfileRegistry, } from './customizations/profile_registry'; import { SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER } from './embeddable/constants'; +import { DiscoverContainerInternal, DiscoverContainerProps } from './components/discover_container'; const DocViewerLegacyTable = React.lazy( () => import('./services/doc_views/components/doc_viewer_table/legacy') @@ -162,6 +163,7 @@ export interface DiscoverStart { * ``` */ readonly locator: undefined | DiscoverAppLocator; + readonly DiscoverContainer: ComponentType; readonly registerCustomizationProfile: RegisterCustomizationProfile; } @@ -420,18 +422,31 @@ export class DiscoverPlugin // initializeServices are assigned at start and used // when the application/embeddable is mounted - const { uiActions } = plugins; - - uiActions.registerTrigger(SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER); - const viewSavedSearchAction = new ViewSavedSearchAction(core.application); - uiActions.addTriggerAction('CONTEXT_MENU_TRIGGER', viewSavedSearchAction); - setUiActions(plugins.uiActions); + plugins.uiActions.addTriggerAction('CONTEXT_MENU_TRIGGER', viewSavedSearchAction); + plugins.uiActions.registerTrigger(SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER); + setUiActions(plugins.uiActions); injectTruncateStyles(core.uiSettings.get(TRUNCATE_MAX_HEIGHT)); + const isDev = this.initializerContext.env.mode.dev; + + const getDiscoverServicesInternal = () => { + return this.getDiscoverServices(core, plugins); + }; + return { locator: this.locator, + DiscoverContainer: ({ overrideServices, ...restProps }: DiscoverContainerProps) => { + return ( + + ); + }, registerCustomizationProfile: createRegisterCustomizationProfile(this.profileRegistry), }; } @@ -442,6 +457,23 @@ export class DiscoverPlugin } } + private getDiscoverServices = async (core: CoreStart, plugins: DiscoverStartPlugins) => { + const { locator, contextLocator, singleDocLocator } = await getProfileAwareLocators({ + locator: this.locator!, + contextLocator: this.contextLocator!, + singleDocLocator: this.singleDocLocator!, + }); + + return buildServices( + core, + plugins, + this.initializerContext, + locator, + contextLocator, + singleDocLocator + ); + }; + private registerEmbeddable(core: CoreSetup, plugins: DiscoverSetupPlugins) { const getStartServices = async () => { const [coreStart, deps] = await core.getStartServices(); @@ -451,25 +483,12 @@ export class DiscoverPlugin }; }; - const getDiscoverServices = async () => { - const [coreStart, discoverStartPlugins] = await core.getStartServices(); - const { locator, contextLocator, singleDocLocator } = await getProfileAwareLocators({ - locator: this.locator!, - contextLocator: this.contextLocator!, - singleDocLocator: this.singleDocLocator!, - }); - - return buildServices( - coreStart, - discoverStartPlugins, - this.initializerContext, - locator, - contextLocator, - singleDocLocator - ); + const getDiscoverServicesInternal = async () => { + const [coreStart, deps] = await core.getStartServices(); + return this.getDiscoverServices(coreStart, deps); }; - const factory = new SearchEmbeddableFactory(getStartServices, getDiscoverServices); + const factory = new SearchEmbeddableFactory(getStartServices, getDiscoverServicesInternal); plugins.embeddable.registerEmbeddableFactory(factory.type, factory); } } diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json index 3b2903f68607968..51377e424612200 100644 --- a/src/plugins/discover/tsconfig.json +++ b/src/plugins/discover/tsconfig.json @@ -3,7 +3,13 @@ "compilerOptions": { "outDir": "target/types" }, - "include": ["common/**/*", "public/**/*", "server/**/*", "../../../typings/**/*", ".storybook/**/*"], + "include": [ + "common/**/*", + "public/**/*", + "server/**/*", + "../../../typings/**/*", + ".storybook/**/*" + ], "kbn_references": [ "@kbn/core", "@kbn/charts-plugin", @@ -55,9 +61,11 @@ "@kbn/unified-field-list", "@kbn/core-saved-objects-api-server", "@kbn/cell-actions", - "@kbn/discover-utils", + "@kbn/shared-ux-utility", + "@kbn/core-application-browser", + "@kbn/discover-utils" ], "exclude": [ - "target/**/*", + "target/**/*" ] } diff --git a/src/plugins/navigation/public/mocks.ts b/src/plugins/navigation/public/mocks.ts index 64e535b6e114a84..e6e4ff5128b0eb7 100644 --- a/src/plugins/navigation/public/mocks.ts +++ b/src/plugins/navigation/public/mocks.ts @@ -23,6 +23,7 @@ const createStartContract = (): jest.Mocked => { const startContract = { ui: { TopNavMenu: jest.fn(), + createTopNavWithCustomContext: jest.fn().mockImplementation(() => jest.fn()), AggregateQueryTopNavMenu: jest.fn(), }, }; diff --git a/src/plugins/navigation/public/plugin.ts b/src/plugins/navigation/public/plugin.ts index e3fe470d9c338c4..3be546918cdc29a 100644 --- a/src/plugins/navigation/public/plugin.ts +++ b/src/plugins/navigation/public/plugin.ts @@ -7,12 +7,14 @@ */ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; +import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import { NavigationPublicPluginSetup, NavigationPublicPluginStart, NavigationPluginStartDependencies, } from './types'; import { TopNavMenuExtensionsRegistry, createTopNav } from './top_nav_menu'; +import { RegisteredTopNavMenuData } from './top_nav_menu/top_nav_menu_data'; export class NavigationPublicPlugin implements Plugin @@ -36,10 +38,31 @@ export class NavigationPublicPlugin ): NavigationPublicPluginStart { const extensions = this.topNavMenuExtensionsRegistry.getAll(); + /* + * + * This helps clients of navigation to create + * a TopNav Search Bar which does not uses global unifiedSearch/data/query service + * + * Useful in creating multiple stateful SearchBar in the same app without affecting + * global filters + * + * */ + const createCustomTopNav = ( + /* + * Custom instance of unified search if it needs to be overridden + * + * */ + customUnifiedSearch?: UnifiedSearchPublicPluginStart, + customExtensions?: RegisteredTopNavMenuData[] + ) => { + return createTopNav(customUnifiedSearch ?? unifiedSearch, customExtensions ?? extensions); + }; + return { ui: { TopNavMenu: createTopNav(unifiedSearch, extensions), AggregateQueryTopNavMenu: createTopNav(unifiedSearch, extensions), + createTopNavWithCustomContext: createCustomTopNav, }, }; } diff --git a/src/plugins/navigation/public/types.ts b/src/plugins/navigation/public/types.ts index a4ca72cf9cb3aff..8958aa91d5ff65b 100644 --- a/src/plugins/navigation/public/types.ts +++ b/src/plugins/navigation/public/types.ts @@ -8,7 +8,8 @@ import { AggregateQuery, Query } from '@kbn/es-query'; import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; -import { TopNavMenuProps, TopNavMenuExtensionsRegistrySetup } from './top_nav_menu'; +import { TopNavMenuProps, TopNavMenuExtensionsRegistrySetup, createTopNav } from './top_nav_menu'; +import { RegisteredTopNavMenuData } from './top_nav_menu/top_nav_menu_data'; export interface NavigationPublicPluginSetup { registerMenuItem: TopNavMenuExtensionsRegistrySetup['register']; @@ -18,6 +19,10 @@ export interface NavigationPublicPluginStart { ui: { TopNavMenu: (props: TopNavMenuProps) => React.ReactElement; AggregateQueryTopNavMenu: (props: TopNavMenuProps) => React.ReactElement; + createTopNavWithCustomContext: ( + customUnifiedSearch?: UnifiedSearchPublicPluginStart, + customExtensions?: RegisteredTopNavMenuData[] + ) => ReturnType; }; } diff --git a/src/plugins/unified_search/public/index.ts b/src/plugins/unified_search/public/index.ts index 8d7a6146e02a50d..b658a21d10cfddb 100755 --- a/src/plugins/unified_search/public/index.ts +++ b/src/plugins/unified_search/public/index.ts @@ -28,6 +28,7 @@ export type { DataViewPickerProps } from './dataview_picker'; export type { ApplyGlobalFilterActionContext } from './actions'; export { ACTION_GLOBAL_APPLY_FILTER, UPDATE_FILTER_REFERENCES_ACTION } from './actions'; export { UPDATE_FILTER_REFERENCES_TRIGGER } from './triggers'; +export { createSearchBar } from './search_bar/create_search_bar'; /* * Autocomplete query suggestions: diff --git a/src/plugins/unified_search/public/mocks/mocks.ts b/src/plugins/unified_search/public/mocks/mocks.ts index d6140fe0ccc99a4..3c2ea2a0a38fe77 100644 --- a/src/plugins/unified_search/public/mocks/mocks.ts +++ b/src/plugins/unified_search/public/mocks/mocks.ts @@ -34,6 +34,7 @@ const createStartContract = (): Start => { autocomplete: autocompleteStartMock, ui: { IndexPatternSelect: jest.fn(), + getCustomSearchBar: jest.fn(), SearchBar: jest.fn().mockReturnValue(null), AggregateQuerySearchBar: jest.fn().mockReturnValue(null), FiltersBuilderLazy: jest.fn(), diff --git a/src/plugins/unified_search/public/plugin.ts b/src/plugins/unified_search/public/plugin.ts index 5aeef71e82d8bba..aa86d433547aff6 100755 --- a/src/plugins/unified_search/public/plugin.ts +++ b/src/plugins/unified_search/public/plugin.ts @@ -20,6 +20,7 @@ import type { UnifiedSearchSetupDependencies, UnifiedSearchPluginSetup, UnifiedSearchPublicPluginStart, + UnifiedSearchPublicPluginStartUi, } from './types'; import { createFilterAction } from './actions/apply_filter_action'; import { createUpdateFilterReferencesAction } from './actions/update_filter_references_action'; @@ -73,16 +74,28 @@ export class UnifiedSearchPublicPlugin setIndexPatterns(dataViews); const autocompleteStart = this.autocomplete.start(); - const SearchBar = createSearchBar({ - core, - data, - storage: this.storage, - usageCollection: this.usageCollection, - isScreenshotMode: Boolean(screenshotMode?.isScreenshotMode()), - unifiedSearch: { - autocomplete: autocompleteStart, - }, - }); + /* + * + * unifiedsearch uses global data service to create stateful search bar. + * This function helps in creating a search bar with different instances of data service + * so that it can be easy to use multiple stateful searchbars in the single applications + * + * */ + const getCustomSearchBar: UnifiedSearchPublicPluginStartUi['getCustomSearchBar'] = ( + customDataService + ) => + createSearchBar({ + core, + data: customDataService ?? data, + storage: this.storage, + usageCollection: this.usageCollection, + isScreenshotMode: Boolean(screenshotMode?.isScreenshotMode()), + unifiedSearch: { + autocomplete: autocompleteStart, + }, + }); + + const SearchBar = getCustomSearchBar(); uiActions.attachAction(APPLY_FILTER_TRIGGER, ACTION_GLOBAL_APPLY_FILTER); @@ -92,6 +105,7 @@ export class UnifiedSearchPublicPlugin ui: { IndexPatternSelect: createIndexPatternSelect(dataViews), SearchBar, + getCustomSearchBar, AggregateQuerySearchBar: SearchBar, FiltersBuilderLazy, }, diff --git a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx index c713bb52e73f6f2..d9dd66bbf15aa4c 100644 --- a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx @@ -23,7 +23,7 @@ import { useSavedQuery } from './lib/use_saved_query'; import { useQueryStringManager } from './lib/use_query_string_manager'; import type { UnifiedSearchPublicPluginStart } from '../types'; -interface StatefulSearchBarDeps { +export interface StatefulSearchBarDeps { core: CoreStart; data: DataPublicPluginStart; storage: IStorageWrapper; diff --git a/src/plugins/unified_search/public/types.ts b/src/plugins/unified_search/public/types.ts index 66abc195b5b193c..a6360b69cca2608 100755 --- a/src/plugins/unified_search/public/types.ts +++ b/src/plugins/unified_search/public/types.ts @@ -20,6 +20,7 @@ import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management import { AutocompleteSetup, AutocompleteStart } from './autocomplete'; import type { IndexPatternSelectProps, StatefulSearchBarProps } from '.'; import type { FiltersBuilderProps } from './filters_builder/filters_builder'; +import { StatefulSearchBarDeps } from './search_bar/create_search_bar'; export interface UnifiedSearchSetupDependencies { uiActions: UiActionsSetup; @@ -39,15 +40,18 @@ export interface UnifiedSearchStartDependencies { screenshotMode?: ScreenshotModePluginStart; } +type AggQuerySearchBarComp = ( + props: StatefulSearchBarProps +) => React.ReactElement; + /** * Unified search plugin prewired UI components */ export interface UnifiedSearchPublicPluginStartUi { IndexPatternSelect: React.ComponentType; + getCustomSearchBar: (customDataService?: StatefulSearchBarDeps['data']) => AggQuerySearchBarComp; SearchBar: (props: StatefulSearchBarProps) => React.ReactElement; - AggregateQuerySearchBar: ( - props: StatefulSearchBarProps - ) => React.ReactElement; + AggregateQuerySearchBar: AggQuerySearchBarComp; FiltersBuilderLazy: React.ComponentType; } diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index f12e31724f8f1b2..b2e1cae53d97e90 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -111,6 +111,12 @@ export const allowedExperimentalValues = Object.freeze({ * Enables experimental Entity Analytics HTTP endpoints */ riskScoringRoutesEnabled: false, + /* + * + * Enables Discover embedded within timeline + * + * */ + discoverInTimeline: true, }); type ExperimentalConfigKeys = Array; diff --git a/x-pack/plugins/security_solution/common/types/timeline/index.ts b/x-pack/plugins/security_solution/common/types/timeline/index.ts index 15c4028dcb8e24d..7148009246dcd79 100644 --- a/x-pack/plugins/security_solution/common/types/timeline/index.ts +++ b/x-pack/plugins/security_solution/common/types/timeline/index.ts @@ -37,6 +37,7 @@ export enum TimelineTabs { eql = 'eql', session = 'session', securityAssistant = 'securityAssistant', + discover = 'discover', } /* diff --git a/x-pack/plugins/security_solution/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts index fe056192b62dc2d..96cd4da1d81305e 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/entity_analytics/entity_analytics_management_page.cy.ts @@ -13,6 +13,7 @@ import { USER_RISK_PREVIEW_TABLE_ROWS, RISK_PREVIEW_ERROR, RISK_PREVIEW_ERROR_BUTTON, + LOCAL_QUERY_BAR_SELECTOR, } from '../../screens/entity_analytics_management'; import { login, visit, visitWithoutDateRange } from '../../tasks/login'; @@ -52,7 +53,7 @@ describe('Entity analytics management page', () => { cy.get(HOST_RISK_PREVIEW_TABLE_ROWS).should('have.length', 5); cy.get(USER_RISK_PREVIEW_TABLE_ROWS).should('have.length', 5); - updateDateRangeInLocalDatePickers(START_DATE, END_DATE); + updateDateRangeInLocalDatePickers(LOCAL_QUERY_BAR_SELECTOR, START_DATE, END_DATE); cy.get(HOST_RISK_PREVIEW_TABLE).contains('No items found'); cy.get(USER_RISK_PREVIEW_TABLE).contains('No items found'); @@ -63,7 +64,7 @@ describe('Entity analytics management page', () => { cy.get(USER_RISK_PREVIEW_TABLE_ROWS).should('have.length', 5); fillLocalSearchBar('host.name: "test-host1"'); - submitLocalSearch(); + submitLocalSearch(LOCAL_QUERY_BAR_SELECTOR); cy.get(HOST_RISK_PREVIEW_TABLE_ROWS).should('have.length', 1); cy.get(HOST_RISK_PREVIEW_TABLE_ROWS).contains('test-host1'); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 4677f3b6d9ad42b..6578ddabf1f4d5e 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -6,6 +6,7 @@ */ import { getDataTestSubjectSelector } from '../helpers/common'; +import { GLOBAL_FILTERS_CONTAINER } from './date_picker'; export const ADD_EXCEPTION_BTN = '[data-test-subj="add-exception-menu-item"]'; @@ -65,7 +66,7 @@ export const MANAGE_ALERT_DETECTION_RULES_BTN = '[data-test-subj="manage-alert-d export const MARK_ALERT_ACKNOWLEDGED_BTN = '[data-test-subj="acknowledged-alert-status"]'; -export const ALERTS_REFRESH_BTN = '[data-test-subj="querySubmitButton"]'; +export const ALERTS_REFRESH_BTN = `${GLOBAL_FILTERS_CONTAINER} [data-test-subj="querySubmitButton"]`; export const ALERTS_HISTOGRAM_PANEL_LOADER = '[data-test-subj="loadingPanelAlertsHistogram"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/date_picker.ts b/x-pack/plugins/security_solution/cypress/screens/date_picker.ts index bbb21f03d6eb09d..5f5a39b96beb951 100644 --- a/x-pack/plugins/security_solution/cypress/screens/date_picker.ts +++ b/x-pack/plugins/security_solution/cypress/screens/date_picker.ts @@ -9,7 +9,9 @@ export const DATE_PICKER_ABSOLUTE_INPUT = '[data-test-subj="superDatePickerAbsol export const LOCAL_DATE_PICKER_APPLY_BUTTON = 'button[data-test-subj="querySubmitButton"]'; -export const DATE_PICKER_APPLY_BUTTON = `[data-test-subj="globalDatePicker"] ${LOCAL_DATE_PICKER_APPLY_BUTTON}`; +export const GLOBAL_FILTERS_CONTAINER = `[data-test-subj="filters-global-container"]`; + +export const DATE_PICKER_APPLY_BUTTON = `${GLOBAL_FILTERS_CONTAINER} ${LOCAL_DATE_PICKER_APPLY_BUTTON}`; export const LOCAL_DATE_PICKER_APPLY_BUTTON_TIMELINE = 'button[data-test-subj="superDatePickerApplyTimeButton"]'; @@ -25,7 +27,9 @@ export const DATE_PICKER_NOW_BUTTON = '[data-test-subj="superDatePickerNowButton export const LOCAL_DATE_PICKER_END_DATE_POPOVER_BUTTON = '[data-test-subj="superDatePickerendDatePopoverButton"]'; -export const DATE_PICKER_END_DATE_POPOVER_BUTTON = `[data-test-subj="globalDatePicker"] ${LOCAL_DATE_PICKER_END_DATE_POPOVER_BUTTON}`; +export const DATE_PICKER_END_DATE_POPOVER_BUTTON = `${GLOBAL_FILTERS_CONTAINER} ${LOCAL_DATE_PICKER_END_DATE_POPOVER_BUTTON}`; + +export const DATE_PICKER_CONTAINER = `${GLOBAL_FILTERS_CONTAINER} .euiSuperDatePicker`; export const DATE_PICKER_END_DATE_POPOVER_BUTTON_TIMELINE = '[data-test-subj="timeline-date-picker-container"] [data-test-subj="superDatePickerendDatePopoverButton"]'; @@ -33,11 +37,12 @@ export const DATE_PICKER_END_DATE_POPOVER_BUTTON_TIMELINE = export const LOCAL_DATE_PICKER_START_DATE_POPOVER_BUTTON = 'button[data-test-subj="superDatePickerstartDatePopoverButton"]'; -export const DATE_PICKER_START_DATE_POPOVER_BUTTON = `div[data-test-subj="globalDatePicker"] ${LOCAL_DATE_PICKER_START_DATE_POPOVER_BUTTON}`; +export const DATE_PICKER_START_DATE_POPOVER_BUTTON = `${GLOBAL_FILTERS_CONTAINER} ${LOCAL_DATE_PICKER_START_DATE_POPOVER_BUTTON}`; -export const GLOBAL_FILTERS_CONTAINER = '[data-test-subj="globalDatePicker"]'; +export const SHOW_DATES_BUTTON = `${GLOBAL_FILTERS_CONTAINER} [data-test-subj="superDatePickerShowDatesButton"]`; -export const SHOW_DATES_BUTTON = '[data-test-subj="superDatePickerShowDatesButton"]'; +export const GET_LOCAL_SHOW_DATES_BUTTON = (localQueryBarSelector: string) => + `${localQueryBarSelector} [data-test-subj="superDatePickerShowDatesButton"]`; export const DATE_PICKER_SHOW_DATE_POPOVER_BUTTON = `${GLOBAL_FILTERS_CONTAINER} ${SHOW_DATES_BUTTON}`; diff --git a/x-pack/plugins/security_solution/cypress/screens/entity_analytics_management.ts b/x-pack/plugins/security_solution/cypress/screens/entity_analytics_management.ts index 660c20a960de60c..f4c0fa83db1eaeb 100644 --- a/x-pack/plugins/security_solution/cypress/screens/entity_analytics_management.ts +++ b/x-pack/plugins/security_solution/cypress/screens/entity_analytics_management.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { getDataTestSubjectSelector } from '../helpers/common'; + export const PAGE_TITLE = '[data-test-subj="entityAnalyticsManagmentPageTitle"]'; export const HOST_RISK_PREVIEW_TABLE = '[data-test-subj="host-risk-preview-table"]'; @@ -18,3 +20,5 @@ export const USER_RISK_PREVIEW_TABLE_ROWS = '[data-test-subj="user-risk-preview- export const RISK_PREVIEW_ERROR = '[data-test-subj="risk-preview-error"]'; export const RISK_PREVIEW_ERROR_BUTTON = '[data-test-subj="risk-preview-error-button"]'; + +export const LOCAL_QUERY_BAR_SELECTOR = getDataTestSubjectSelector('risk-score-preview-search-bar'); diff --git a/x-pack/plugins/security_solution/cypress/screens/search_bar.ts b/x-pack/plugins/security_solution/cypress/screens/search_bar.ts index 1ffd7204511083d..d90532f8504f3d3 100644 --- a/x-pack/plugins/security_solution/cypress/screens/search_bar.ts +++ b/x-pack/plugins/security_solution/cypress/screens/search_bar.ts @@ -5,12 +5,15 @@ * 2.0. */ +export const GLOBAL_KQL_WRAPPER = '[data-test-subj="filters-global-container"]'; + export const GLOBAL_SEARCH_BAR_ADD_FILTER = '[data-test-subj="globalDatePicker"] [data-test-subj="addFilter"]'; -export const LOCAL_SEACH_BAR_SUBMMIT_BUTTON = '[data-test-subj="querySubmitButton"]'; +export const GLOBAL_SEARCH_BAR_SUBMIT_BUTTON = `${GLOBAL_KQL_WRAPPER} [data-test-subj="querySubmitButton"]`; -export const GLOBAL_SEARCH_BAR_SUBMIT_BUTTON = `[data-test-subj="globalDatePicker"] ${LOCAL_SEACH_BAR_SUBMMIT_BUTTON}`; +export const GET_LOCAL_SEARCH_BAR_SUBMIT_BUTTON = (localSearchBarSelector: string) => + `${localSearchBarSelector ?? ''} [data-test-subj="querySubmitButton"]`; export const ADD_FILTER_FORM_FIELD_INPUT = '[data-test-subj="filterFieldSuggestionList"] input[data-test-subj="comboBoxSearchInput"]'; @@ -36,8 +39,6 @@ export const GLOBAL_SEARCH_BAR_FILTER_ITEM_DELETE = '#popoverFor_filter0 button[ export const GLOBAL_SEARCH_BAR_PINNED_FILTER = '.globalFilterItem-isPinned'; -export const GLOBAL_KQL_WRAPPER = '[data-test-subj="filters-global-container"]'; - export const LOCAL_KQL_INPUT = `[data-test-subj="unifiedQueryInput"] textarea`; export const GLOBAL_KQL_INPUT = `[data-test-subj="filters-global-container"] ${LOCAL_KQL_INPUT}`; diff --git a/x-pack/plugins/security_solution/cypress/screens/security_header.ts b/x-pack/plugins/security_solution/cypress/screens/security_header.ts index 9bf01fef56b24b2..2720e4e1a60e3fa 100644 --- a/x-pack/plugins/security_solution/cypress/screens/security_header.ts +++ b/x-pack/plugins/security_solution/cypress/screens/security_header.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { GLOBAL_KQL_WRAPPER } from './search_bar'; + // main links export const DASHBOARDS = '[data-test-subj="solutionSideNavItemLink-dashboards"]'; export const DASHBOARDS_PANEL_BTN = '[data-test-subj="solutionSideNavItemButton-dashboards"]'; @@ -68,9 +70,9 @@ export const EXCEPTIONS = '[data-test-subj="solutionSideNavPanelLink-exceptions" // other export const BREADCRUMBS = '[data-test-subj="breadcrumbs"] a'; -export const KQL_INPUT = '[data-test-subj="queryInput"]'; +export const KQL_INPUT = `${GLOBAL_KQL_WRAPPER} [data-test-subj="queryInput"]`; -export const REFRESH_BUTTON = '[data-test-subj="querySubmitButton"]'; +export const REFRESH_BUTTON = `${GLOBAL_KQL_WRAPPER} [data-test-subj="querySubmitButton"]`; export const LOADING_INDICATOR = '[data-test-subj="globalLoadingIndicator"]'; export const LOADING_INDICATOR_HIDDEN = '[data-test-subj="globalLoadingIndicator-hidden"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/timeline.ts b/x-pack/plugins/security_solution/cypress/screens/timeline.ts index d46b0d04f3355a0..3b3639f9234d532 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timeline.ts @@ -9,7 +9,8 @@ import type { TimelineFilter } from '../objects/timeline'; export const ADD_NOTE_BUTTON = '[data-test-subj="add-note"]'; -export const ADD_FILTER = '[data-test-subj="timeline"] [data-test-subj="addFilter"]'; +export const ADD_FILTER = + '[data-test-subj="timeline-search-or-filter"] [data-test-subj="addFilter"]'; export const ATTACH_TIMELINE_TO_CASE_BUTTON = '[data-test-subj="attach-timeline-case-button"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/date_picker.ts b/x-pack/plugins/security_solution/cypress/tasks/date_picker.ts index a3b7a3f0ce1ec65..4a74ac3ddd7fa47 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/date_picker.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/date_picker.ts @@ -13,7 +13,6 @@ import { DATE_PICKER_END_DATE_POPOVER_BUTTON, DATE_PICKER_END_DATE_POPOVER_BUTTON_TIMELINE, DATE_PICKER_START_DATE_POPOVER_BUTTON, - GLOBAL_FILTERS_CONTAINER, SHOW_DATES_BUTTON, DATE_PICKER_START_DATE_POPOVER_BUTTON_TIMELINE, DATE_PICKER_SHOW_DATE_POPOVER_BUTTON, @@ -21,6 +20,8 @@ import { DATE_PICKER_NOW_BUTTON, LOCAL_DATE_PICKER_APPLY_BUTTON, LOCAL_DATE_PICKER_END_DATE_POPOVER_BUTTON, + DATE_PICKER_CONTAINER, + GET_LOCAL_SHOW_DATES_BUTTON, } from '../screens/date_picker'; export const setEndDate = (date: string) => { @@ -42,8 +43,7 @@ export const setEndDateNow = () => { }; export const setStartDate = (date: string) => { - cy.get(GLOBAL_FILTERS_CONTAINER); - cy.get('.euiSuperDatePicker'); + cy.get(DATE_PICKER_CONTAINER).should('be.visible'); cy.get('body').then(($container) => { if ($container.find(SHOW_DATES_BUTTON).length > 0) { cy.get(DATE_PICKER_SHOW_DATE_POPOVER_BUTTON).click({ force: true }); @@ -101,8 +101,12 @@ export const updateTimelineDates = () => { cy.get(DATE_PICKER_APPLY_BUTTON_TIMELINE).first().should('not.have.text', 'Updating'); }; -export const updateDateRangeInLocalDatePickers = (startDate: string, endDate: string) => { - cy.get(SHOW_DATES_BUTTON).click(); +export const updateDateRangeInLocalDatePickers = ( + localQueryBarSelector: string, + startDate: string, + endDate: string +) => { + cy.get(GET_LOCAL_SHOW_DATES_BUTTON(localQueryBarSelector)).click(); cy.get(DATE_PICKER_ABSOLUTE_TAB).first().click(); cy.get(DATE_PICKER_ABSOLUTE_INPUT).click(); diff --git a/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts b/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts index 144b71f5b2ff578..94d3d064d8e0e73 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts @@ -18,7 +18,7 @@ import { ADD_FILTER_FORM_FILTER_VALUE_INPUT, GLOBAL_KQL_INPUT, LOCAL_KQL_INPUT, - LOCAL_SEACH_BAR_SUBMMIT_BUTTON, + GET_LOCAL_SEARCH_BAR_SUBMIT_BUTTON, } from '../screens/search_bar'; export const openAddFilterPopover = () => { @@ -72,6 +72,6 @@ export const fillLocalSearchBar = (query: string) => { cy.get(LOCAL_KQL_INPUT).type(query); }; -export const submitLocalSearch = () => { - cy.get(LOCAL_SEACH_BAR_SUBMMIT_BUTTON).click(); +export const submitLocalSearch = (localSearchBarSelector: string) => { + cy.get(GET_LOCAL_SEARCH_BAR_SUBMIT_BUTTON(localSearchBarSelector)).click(); }; diff --git a/x-pack/plugins/security_solution/kibana.jsonc b/x-pack/plugins/security_solution/kibana.jsonc index 8f3ced69de6e313..f4716adfca310d1 100644 --- a/x-pack/plugins/security_solution/kibana.jsonc +++ b/x-pack/plugins/security_solution/kibana.jsonc @@ -6,7 +6,10 @@ "id": "securitySolution", "server": true, "browser": true, - "configPath": ["xpack", "securitySolution"], + "configPath": [ + "xpack", + "securitySolution" + ], "requiredPlugins": [ "actions", "alerting", @@ -29,6 +32,7 @@ "lens", "licensing", "maps", + "navigation", "ruleRegistry", "sessionView", "spaces", @@ -40,8 +44,11 @@ "unifiedSearch", "files", "controls", + "dataViewEditor", "savedObjectsManagement", - "stackConnectors" + "stackConnectors", + "discover", + "notifications" ], "optionalPlugins": [ "cloudExperiments", @@ -69,6 +76,8 @@ "unifiedSearch", "cloudChat" ], - "extraPublicDirs": ["common"] + "extraPublicDirs": [ + "common" + ] } } diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index de9750af2541cd9..0d192428c081e8e 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -10,6 +10,8 @@ import React from 'react'; import type { RecursivePartial } from '@elastic/eui/src/components/common'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; +import { navigationPluginMock } from '@kbn/navigation-plugin/public/mocks'; +import { discoverPluginMock } from '@kbn/discover-plugin/public/mocks'; import { coreMock, themeServiceMock } from '@kbn/core/public/mocks'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; @@ -102,11 +104,14 @@ export const createStartServicesMock = ( const { storage } = createSecuritySolutionStorageMock(); const apm = mockApm(); const data = dataPluginMock.createStartContract(); + const customDataService = dataPluginMock.createStartContract(); const security = securityMock.createSetup(); const urlService = new MockUrlService(); const locator = urlService.locators.create(new MlLocatorDefinition()); const fleet = fleetMock.createStartMock(); const unifiedSearch = unifiedSearchPluginMock.createStartContract(); + const navigation = navigationPluginMock.createStartContract(); + const discover = discoverPluginMock.createStartContract(); const cases = mockCasesContract(); const dataViewServiceMock = dataViewPluginMocks.createStartContract(); cases.helpers.getUICapabilities.mockReturnValue(noCasesPermissions()); @@ -119,6 +124,8 @@ export const createStartServicesMock = ( apm, cases, unifiedSearch, + navigation, + discover, dataViews: dataViewServiceMock, data: { ...data, @@ -193,6 +200,7 @@ export const createStartServicesMock = ( guidedOnboarding, isSidebarEnabled$: of(true), upselling: new UpsellingService(), + customDataService, } as unknown as StartServices; }; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx index d5fc0c3fd91074a..5636daa39f4e6e4 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx @@ -156,7 +156,7 @@ export const RiskScorePreviewSection = () => { {i18n.PREVIEW_DESCRIPTION} - + {indexPattern && ( { - cy.getByTestSubj('queryInput').click().type(text); - cy.getByTestSubj('querySubmitButton').click(); + cy.getByTestSubj('filters-global-container').within(() => { + cy.getByTestSubj('queryInput').click().type(text); + cy.getByTestSubj('querySubmitButton').click(); + }); }; diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 0a54b27cfa9fda8..caa9dc3735e99a0 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -16,6 +16,8 @@ import type { PluginInitializerContext, Plugin as IPlugin, } from '@kbn/core/public'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { FilterManager, NowProvider, QueryService } from '@kbn/data-plugin/public'; import { DEFAULT_APP_CATEGORIES, AppNavLinkStatus } from '@kbn/core/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import type { @@ -79,6 +81,8 @@ export class Plugin implements IPlugin(); @@ -90,6 +94,7 @@ export class Plugin implements IPlugin(); @@ -124,6 +129,12 @@ export class Plugin implements IPlugin { ); + await waitFor(() => { expect(EmptyComponent.getByTestId('flyout-pane')).toHaveStyle('display: block'); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/index.test.tsx new file mode 100644 index 000000000000000..db874f9a812458c --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/index.test.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 { TestProviders } from '../../../../common/mock'; +import DiscoverTabContent from '.'; +import { render, screen, waitFor } from '@testing-library/react'; + +const TestComponent = () => { + return ( + + + + ); +}; + +describe('Discover Tab Content', () => { + it('renders', async () => { + render(); + + await waitFor(() => { + expect(screen.getByTestId('timeline-embedded-discover')).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/index.tsx new file mode 100644 index 000000000000000..d853baefbbd8efa --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/index.tsx @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo } from 'react'; +import { useHistory } from 'react-router-dom'; +import type { CustomizationCallback } from '@kbn/discover-plugin/public/customizations/types'; +import styled, { createGlobalStyle } from 'styled-components'; +import type { ScopedHistory } from '@kbn/core/public'; +import { useKibana } from '../../../../common/lib/kibana'; +import { useGetStatefulQueryBar } from './use_get_stateful_query_bar'; + +const HideSearchSessionIndicatorBreadcrumbIcon = createGlobalStyle` + [data-test-subj='searchSessionIndicator'] { + display: none; + } +`; + +const EmbeddedDiscoverContainer = styled.div` + width: 100%; + height: 100%; + overflow: scroll; + display: grid, + place-items: center +`; + +export const DiscoverTabContent = () => { + const history = useHistory(); + const { + services: { customDataService: discoverDataService, discover, discoverFilterManager }, + } = useKibana(); + + const { CustomStatefulTopNavKqlQueryBar } = useGetStatefulQueryBar(); + + const customize: CustomizationCallback = useCallback( + ({ customizations }) => { + customizations.set({ + id: 'search_bar', + CustomSearchBar: CustomStatefulTopNavKqlQueryBar, + }); + }, + [CustomStatefulTopNavKqlQueryBar] + ); + + const services = useMemo( + () => ({ + filterManager: discoverFilterManager, + data: discoverDataService, + }), + [discoverDataService, discoverFilterManager] + ); + + const DiscoverContainer = discover.DiscoverContainer; + + return ( + + + + + ); +}; + +// eslint-disable-next-line import/no-default-export +export default DiscoverTabContent; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/use_get_stateful_query_bar.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/use_get_stateful_query_bar.test.tsx new file mode 100644 index 000000000000000..6f3951e3ecac110 --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/use_get_stateful_query_bar.test.tsx @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TestProviders } from '../../../../common/mock'; +import { renderHook } from '@testing-library/react-hooks'; +import { useGetStatefulQueryBar } from './use_get_stateful_query_bar'; + +describe('useGetStatefulQueryBar', () => { + it('returns custom QueryBar', async () => { + const { result } = renderHook(() => useGetStatefulQueryBar(), { + wrapper: TestProviders, + }); + + expect(result.current).toHaveProperty('CustomStatefulTopNavKqlQueryBar'); + expect(result.current.CustomStatefulTopNavKqlQueryBar).not.toBeUndefined(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/use_get_stateful_query_bar.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/use_get_stateful_query_bar.tsx new file mode 100644 index 000000000000000..61ccaeaef2a650d --- /dev/null +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/discover_tab_content/use_get_stateful_query_bar.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import { useKibana } from '../../../../common/lib/kibana'; + +export const useGetStatefulQueryBar = () => { + const { + services: { + navigation: { + ui: { createTopNavWithCustomContext }, + }, + unifiedSearch, + customDataService, + }, + } = useKibana(); + + const { + ui: { getCustomSearchBar }, + } = unifiedSearch; + + const CustomSearchBar = useMemo( + () => getCustomSearchBar(customDataService), + [customDataService, getCustomSearchBar] + ); + + const CustomStatefulTopNavKqlQueryBar = useMemo(() => { + const customUnifiedSearch = { + ...unifiedSearch, + ui: { + ...unifiedSearch.ui, + SearchBar: CustomSearchBar, + AggregateQuerySearchBar: CustomSearchBar, + }, + }; + + return createTopNavWithCustomContext(customUnifiedSearch); + }, [CustomSearchBar, createTopNavWithCustomContext, unifiedSearch]); + + return { + CustomStatefulTopNavKqlQueryBar, + }; +}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx index f6bf0adf45a156f..15bcf2ed0f01110 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx @@ -9,10 +9,12 @@ import { EuiBadge, EuiSkeletonText, EuiTabs, EuiTab } from '@elastic/eui'; import { css } from '@emotion/react'; import { Assistant } from '@kbn/elastic-assistant'; import { isEmpty } from 'lodash/fp'; +import type { Ref, ReactElement, ComponentType } from 'react'; import React, { lazy, memo, Suspense, useCallback, useEffect, useMemo } from 'react'; import { useDispatch } from 'react-redux'; import styled from 'styled-components'; +import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useConversationStore } from '../../../../assistant/use_conversation_store'; import { useAssistantAvailability } from '../../../../assistant/use_assistant_availability'; import type { SessionViewConfig } from '../../../../../common/types'; @@ -52,17 +54,37 @@ const HideShowContainer = styled.div.attrs<{ $isVisible: boolean; isOverflowYScr flex: 1; `; +/** + * A HOC which supplies React.Suspense with a fallback component + * @param Component A component deferred by `React.lazy` + * @param fallback A fallback component to render while things load. Default is EuiSekeleton for all tabs + */ +const tabWithSuspense =

( + Component: ComponentType

, + fallback: ReactElement | null = +) => { + const Comp = React.forwardRef((props: P, ref: Ref) => ( + + + + )); + + Comp.displayName = `${Component.displayName ?? 'Tab'}WithSuspense`; + return Comp; +}; + const AssistantTabContainer = styled.div` overflow-y: auto; width: 100%; `; -const QueryTabContent = lazy(() => import('../query_tab_content')); -const EqlTabContent = lazy(() => import('../eql_tab_content')); -const GraphTabContent = lazy(() => import('../graph_tab_content')); -const NotesTabContent = lazy(() => import('../notes_tab_content')); -const PinnedTabContent = lazy(() => import('../pinned_tab_content')); -const SessionTabContent = lazy(() => import('../session_tab_content')); +const QueryTab = tabWithSuspense(lazy(() => import('../query_tab_content'))); +const EqlTab = tabWithSuspense(lazy(() => import('../eql_tab_content'))); +const GraphTab = tabWithSuspense(lazy(() => import('../graph_tab_content'))); +const NotesTab = tabWithSuspense(lazy(() => import('../notes_tab_content'))); +const PinnedTab = tabWithSuspense(lazy(() => import('../pinned_tab_content'))); +const SessionTab = tabWithSuspense(lazy(() => import('../session_tab_content'))); +const DiscoverTab = tabWithSuspense(lazy(() => import('../discover_tab_content'))); interface BasicTimelineTab { renderCellValue: (props: CellValueElementProps) => React.ReactNode; @@ -75,72 +97,6 @@ interface BasicTimelineTab { timelineDescription: string; } -const QueryTab: React.FC<{ - renderCellValue: (props: CellValueElementProps) => React.ReactNode; - rowRenderers: RowRenderer[]; - timelineId: TimelineId; -}> = memo(({ renderCellValue, rowRenderers, timelineId }) => ( - }> - - -)); -QueryTab.displayName = 'QueryTab'; - -const EqlTab: React.FC<{ - renderCellValue: (props: CellValueElementProps) => React.ReactNode; - rowRenderers: RowRenderer[]; - timelineId: TimelineId; -}> = memo(({ renderCellValue, rowRenderers, timelineId }) => ( - }> - - -)); -EqlTab.displayName = 'EqlTab'; - -const GraphTab: React.FC<{ timelineId: TimelineId }> = memo(({ timelineId }) => ( - }> - - -)); -GraphTab.displayName = 'GraphTab'; - -const NotesTab: React.FC<{ timelineId: TimelineId }> = memo(({ timelineId }) => ( - }> - - -)); -NotesTab.displayName = 'NotesTab'; - -const SessionTab: React.FC<{ timelineId: TimelineId }> = memo(({ timelineId }) => ( - }> - - -)); -SessionTab.displayName = 'SessionTab'; - -const PinnedTab: React.FC<{ - renderCellValue: (props: CellValueElementProps) => React.ReactNode; - rowRenderers: RowRenderer[]; - timelineId: TimelineId; -}> = memo(({ renderCellValue, rowRenderers, timelineId }) => ( - }> - - -)); -PinnedTab.displayName = 'PinnedTab'; - const AssistantTab: React.FC<{ isAssistantEnabled: boolean; renderCellValue: (props: CellValueElementProps) => React.ReactNode; @@ -177,6 +133,7 @@ const ActiveTimelineTab = memo( timelineType, showTimeline, }) => { + const isDiscoverInTimelineEnabled = useIsExperimentalFeatureEnabled('discoverInTimeline'); const { hasAssistantPrivilege, isAssistantEnabled } = useAssistantAvailability(); const getTab = useCallback( (tab: TimelineTabs) => { @@ -276,6 +233,14 @@ const ActiveTimelineTab = memo( )} )} + {isDiscoverInTimelineEnabled && ( + + + + )} ); } @@ -313,6 +278,7 @@ const TabsContentComponent: React.FC = ({ sessionViewConfig, timelineDescription, }) => { + const isDiscoverInTimelineEnabled = useIsExperimentalFeatureEnabled('discoverInTimeline'); const { hasAssistantPrivilege } = useAssistantAvailability(); const dispatch = useDispatch(); const getActiveTab = useMemo(() => getActiveTabSelector(), []); @@ -388,6 +354,10 @@ const TabsContentComponent: React.FC = ({ setActiveTab(TimelineTabs.securityAssistant); }, [setActiveTab]); + const setDiscoverAsActiveTab = useCallback(() => { + setActiveTab(TimelineTabs.discover); + }, [setActiveTab]); + useEffect(() => { if (!graphEventId && activeTab === TimelineTabs.graph) { setQueryAsActiveTab(); @@ -479,6 +449,17 @@ const TabsContentComponent: React.FC = ({ {i18n.SECURITY_ASSISTANT} )} + {isDiscoverInTimelineEnabled && ( + + {i18n.DISCOVER_IN_TIMELINE_TAB} + + )} )} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/translations.ts b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/translations.ts index f8daba8330a43fa..e900af321c03092 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/translations.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/translations.ts @@ -46,6 +46,13 @@ export const SECURITY_ASSISTANT = i18n.translate( } ); +export const DISCOVER_IN_TIMELINE_TAB = i18n.translate( + 'xpack.securitySolution.timeline.tabs.discoverInTimeline', + { + defaultMessage: 'Discover', + } +); + export const SESSION_TAB = i18n.translate( 'xpack.securitySolution.timeline.tabs.sessionTabTimelineTitle', { diff --git a/x-pack/plugins/security_solution/public/types.ts b/x-pack/plugins/security_solution/public/types.ts index 358111dd5526500..62924b89b872cc9 100644 --- a/x-pack/plugins/security_solution/public/types.ts +++ b/x-pack/plugins/security_solution/public/types.ts @@ -9,7 +9,7 @@ import type { Observable } from 'rxjs'; import type { AppLeaveHandler, CoreStart } from '@kbn/core/public'; import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; -import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { DataPublicPluginStart, FilterManager } from '@kbn/data-plugin/public'; import type { FieldFormatsStartCommon } from '@kbn/field-formats-plugin/common'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; @@ -50,6 +50,9 @@ import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/ import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; +import type { DiscoverStart } from '@kbn/discover-plugin/public'; +import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public'; +import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; import type { ResolverPluginSetup } from './resolver/types'; import type { Inspect } from '../common/search_strategy'; import type { Detections } from './detections'; @@ -122,6 +125,9 @@ export interface StartPlugins { cloudExperiments?: CloudExperimentsPluginStart; dataViews: DataViewsServicePublic; fieldFormats: FieldFormatsStartCommon; + discover: DiscoverStart; + navigation: NavigationPublicPluginStart; + dataViewEditor: DataViewEditorStart; } export interface StartPluginsDependencies extends StartPlugins { @@ -153,6 +159,8 @@ export type StartServices = CoreStart & }; savedObjectsManagement: SavedObjectsManagementPluginStart; telemetry: TelemetryClientStart; + discoverFilterManager: FilterManager; + customDataService: DataPublicPluginStart; }; export interface PluginSetup { diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index 01987641931a72f..3828a6839cd6c06 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -161,6 +161,9 @@ "@kbn/field-formats-plugin", "@kbn/dev-proc-runner", "@kbn/cloud-chat-plugin", + "@kbn/discover-plugin", + "@kbn/navigation-plugin", + "@kbn/data-view-editor-plugin", "@kbn/alerts-ui-shared" ] } From 1c3f4a8543ab24c994dbc1d061e047a9c7e9bef3 Mon Sep 17 00:00:00 2001 From: James Rodewig Date: Tue, 25 Jul 2023 06:08:21 -0400 Subject: [PATCH 08/29] [DOCS] Remove outdated Maps video (#161991) - Removes a video from the [Maps](https://www.elastic.co/guide/en/kibana/current/maps.html) docs. The video's UI is outdated. There are no current plans to update the video. - Adds a comment to the [Make dashboards interactive](https://www.elastic.co/guide/en/kibana/current/drilldowns.html). This video is slightly outdated, but we're leaving it in at the request of the dev team. Closes https://github.com/elastic/platform-docs-team/issues/131 --- docs/maps/index.asciidoc | 16 ---------------- .../make-dashboards-interactive.asciidoc | 3 +++ 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/docs/maps/index.asciidoc b/docs/maps/index.asciidoc index e6446a2a30075cc..f924e60cce9e6e8 100644 --- a/docs/maps/index.asciidoc +++ b/docs/maps/index.asciidoc @@ -13,22 +13,6 @@ Create beautiful maps from your geographical data. With **Maps**, you can: * Symbolize features using data values. * Focus on only the data that’s important to you. -*Ready to get started?* Watch the https://videos.elastic.co/watch/BYzRDtH4u7RSD8wKhuEW1b[video], and then start your tour of **Maps** with the <>. - -++++ - - -
-++++ - [float] === Build maps with multiple layers and indices Use multiple layers and indices to show all your data in a single map. Show how data sits relative to physical features like weather patterns, human-made features like international borders, and business-specific features like sales regions. Plot individual documents or use aggregations to plot any data set, no matter how large. diff --git a/docs/user/dashboard/make-dashboards-interactive.asciidoc b/docs/user/dashboard/make-dashboards-interactive.asciidoc index 1ebcc2ca2402ffe..aee1d37507f19f1 100644 --- a/docs/user/dashboard/make-dashboards-interactive.asciidoc +++ b/docs/user/dashboard/make-dashboards-interactive.asciidoc @@ -9,6 +9,9 @@ Add interactive capabilities to your dashboard, such as interactive filter controls, and drilldowns that allow you to navigate to *Discover*, other dashboards, and external websites. +// Video is slightly outdated. Left in at request of dev team. +// See https://github.com/elastic/kibana/pull/161090#issuecomment-1620410065 + ++++ From 707ed134be878ea314b0df5d73c078d9a4e58f26 Mon Sep 17 00:00:00 2001 From: Ido Cohen <90558359+CohenIdo@users.noreply.github.com> Date: Tue, 25 Jul 2023 13:17:45 +0300 Subject: [PATCH 09/29] [serverless] add cspm metering functionality (#162019) --- .../cloud_security/cloud_security_metring.ts | 46 ++++++ .../cloud_security/cspm_metring_task.ts | 110 +++++++++++++ .../cloud_security/metering_tasks_configs.ts | 20 +++ .../services/usage_reporting_service.ts | 2 +- .../server/plugin.ts | 21 ++- .../task_manager/usage_reporting_task.ts | 154 ++++++++++-------- .../server/types.ts | 56 ++++++- .../tsconfig.json | 8 +- 8 files changed, 334 insertions(+), 83 deletions(-) create mode 100644 x-pack/plugins/security_solution_serverless/server/cloud_security/cloud_security_metring.ts create mode 100644 x-pack/plugins/security_solution_serverless/server/cloud_security/cspm_metring_task.ts create mode 100644 x-pack/plugins/security_solution_serverless/server/cloud_security/metering_tasks_configs.ts diff --git a/x-pack/plugins/security_solution_serverless/server/cloud_security/cloud_security_metring.ts b/x-pack/plugins/security_solution_serverless/server/cloud_security/cloud_security_metring.ts new file mode 100644 index 000000000000000..25fb2b3fdefcce3 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/server/cloud_security/cloud_security_metring.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getCspmUsageRecord } from './cspm_metring_task'; +import type { MeteringCallbackInput, UsageRecord } from '../types'; + +export const CLOUD_SECURITY_TASK_TYPE = 'Cloud_Security'; + +export const cloudSecurityMetringCallback = async ({ + esClient, + cloudSetup, + logger, + taskId, + lastSuccessfulReport, +}: MeteringCallbackInput): Promise => { + const projectId = cloudSetup?.serverless?.projectId || 'missing project id'; + + if (!cloudSetup?.serverless?.projectId) { + logger.error('no project id found'); + } + + try { + const cloudSecurityUsageRecords: UsageRecord[] = []; + + const cspmUsageRecord = await getCspmUsageRecord({ + esClient, + projectId, + logger, + taskId, + lastSuccessfulReport, + }); + + if (cspmUsageRecord) { + cloudSecurityUsageRecords.push(cspmUsageRecord); + } + + return cloudSecurityUsageRecords; + } catch (err) { + logger.error(`Failed to fetch Cloud Security metering data ${err}`); + return []; + } +}; diff --git a/x-pack/plugins/security_solution_serverless/server/cloud_security/cspm_metring_task.ts b/x-pack/plugins/security_solution_serverless/server/cloud_security/cspm_metring_task.ts new file mode 100644 index 000000000000000..a217046c32ca1e4 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/server/cloud_security/cspm_metring_task.ts @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + CSPM_POLICY_TEMPLATE, + CSP_LATEST_FINDINGS_DATA_VIEW, +} from '@kbn/cloud-security-posture-plugin/common/constants'; +import { CLOUD_SECURITY_TASK_TYPE } from './cloud_security_metring'; +import { cloudSecurityMetringTaskProperties } from './metering_tasks_configs'; + +import type { CloudSecurityMeteringCallbackInput, UsageRecord } from '../types'; + +const CSPM_CYCLE_SCAN_FREQUENT = '24h'; +const CSPM_BUCKET_SUB_TYPE_NAME = 'CSPM'; + +interface ResourceCountAggregation { + min_timestamp: MinTimestamp; + unique_resources: { + value: number; + }; +} + +interface MinTimestamp { + value: number; + value_as_string: string; +} + +export const getCspmUsageRecord = async ({ + esClient, + projectId, + logger, + taskId, +}: CloudSecurityMeteringCallbackInput): Promise => { + try { + const response = await esClient.search( + getFindingsByResourceAggQuery() + ); + + if (!response.aggregations) { + return; + } + const cspmResourceCount = response.aggregations.unique_resources.value; + + const minTimestamp = response.aggregations + ? new Date(response.aggregations.min_timestamp.value_as_string).toISOString() + : new Date().toISOString(); + + const usageRecords = { + id: `${CLOUD_SECURITY_TASK_TYPE}:${CLOUD_SECURITY_TASK_TYPE}`, + usage_timestamp: minTimestamp, + creation_timestamp: new Date().toISOString(), + usage: { + type: CLOUD_SECURITY_TASK_TYPE, + sub_type: CSPM_BUCKET_SUB_TYPE_NAME, + quantity: cspmResourceCount, + period_seconds: cloudSecurityMetringTaskProperties.periodSeconds, + }, + source: { + id: taskId, + instance_group_id: projectId, + }, + }; + + logger.debug(`Fetched CSPM metring data`); + + return usageRecords; + } catch (err) { + logger.error(`Failed to fetch CSPM metering data ${err}`); + } +}; + +export const getFindingsByResourceAggQuery = () => ({ + index: CSP_LATEST_FINDINGS_DATA_VIEW, + query: { + bool: { + must: [ + { + term: { + 'rule.benchmark.posture_type': CSPM_POLICY_TEMPLATE, + }, + }, + { + range: { + '@timestamp': { + gte: `now-${CSPM_CYCLE_SCAN_FREQUENT}`, // the "look back" period should be the same as the scan interval + }, + }, + }, + ], + }, + }, + size: 0, + aggs: { + unique_resources: { + cardinality: { + field: 'resource.id', + precision_threshold: 3000, // default = 3000 note note that even with a threshold as low as 100, the error remains very low 1-6% even when counting millions of items. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html#_counts_are_approximate + }, + }, + min_timestamp: { + min: { + field: '@timestamp', + }, + }, + }, +}); diff --git a/x-pack/plugins/security_solution_serverless/server/cloud_security/metering_tasks_configs.ts b/x-pack/plugins/security_solution_serverless/server/cloud_security/metering_tasks_configs.ts new file mode 100644 index 000000000000000..46b4f16ed39e405 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/server/cloud_security/metering_tasks_configs.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { cloudSecurityMetringCallback } from './cloud_security_metring'; +import type { MetringTaskProperties } from '../types'; + +const TASK_INTERVAL = 3600; // 1 hour + +export const cloudSecurityMetringTaskProperties: MetringTaskProperties = { + taskType: 'cloud-security-usage-reporting-task', + taskTitle: 'Cloud Security Metring Periodic Tasks', + meteringCallback: cloudSecurityMetringCallback, + interval: `${TASK_INTERVAL.toString()}s`, + periodSeconds: TASK_INTERVAL, + version: '1', +}; diff --git a/x-pack/plugins/security_solution_serverless/server/common/services/usage_reporting_service.ts b/x-pack/plugins/security_solution_serverless/server/common/services/usage_reporting_service.ts index f6ca7a52b3342e5..aae47c8de9f247d 100644 --- a/x-pack/plugins/security_solution_serverless/server/common/services/usage_reporting_service.ts +++ b/x-pack/plugins/security_solution_serverless/server/common/services/usage_reporting_service.ts @@ -15,7 +15,7 @@ export class UsageReportingService { public async reportUsage(records: UsageRecord[]): Promise { return fetch(USAGE_SERVICE_USAGE_URL, { method: 'post', - body: JSON.stringify([records]), + body: JSON.stringify(records), headers: { 'Content-Type': 'application/json' }, }); } diff --git a/x-pack/plugins/security_solution_serverless/server/plugin.ts b/x-pack/plugins/security_solution_serverless/server/plugin.ts index b4801eff7553357..d8fa96d6f51806d 100644 --- a/x-pack/plugins/security_solution_serverless/server/plugin.ts +++ b/x-pack/plugins/security_solution_serverless/server/plugin.ts @@ -15,6 +15,8 @@ import type { SecuritySolutionServerlessPluginSetupDeps, SecuritySolutionServerlessPluginStartDeps, } from './types'; +import { SecurityUsageReportingTask } from './task_manager/usage_reporting_task'; +import { cloudSecurityMetringTaskProperties } from './cloud_security/metering_tasks_configs'; export class SecuritySolutionServerlessPlugin implements @@ -26,6 +28,7 @@ export class SecuritySolutionServerlessPlugin > { private config: ServerlessSecurityConfig; + private cspmUsageReportingTask: SecurityUsageReportingTask | undefined; constructor(private readonly initializerContext: PluginInitializerContext) { this.config = this.initializerContext.config.get(); @@ -35,17 +38,33 @@ export class SecuritySolutionServerlessPlugin // securitySolutionEss plugin should always be disabled when securitySolutionServerless is enabled. // This check is an additional layer of security to prevent double registrations when // `plugins.forceEnableAllPlugins` flag is enabled). + const shouldRegister = pluginsSetup.securitySolutionEss == null; if (shouldRegister) { pluginsSetup.securitySolution.setAppFeatures(getProductAppFeatures(this.config.productTypes)); } - pluginsSetup.ml.setFeaturesEnabled({ ad: true, dfa: true, nlp: false }); + + this.cspmUsageReportingTask = new SecurityUsageReportingTask({ + core: _coreSetup, + logFactory: this.initializerContext.logger, + taskManager: pluginsSetup.taskManager, + cloudSetup: pluginsSetup.cloudSetup, + taskType: cloudSecurityMetringTaskProperties.taskType, + taskTitle: cloudSecurityMetringTaskProperties.taskTitle, + version: cloudSecurityMetringTaskProperties.version, + meteringCallback: cloudSecurityMetringTaskProperties.meteringCallback, + }); + return {}; } public start(_coreStart: CoreStart, pluginsSetup: SecuritySolutionServerlessPluginStartDeps) { + this.cspmUsageReportingTask?.start({ + taskManager: pluginsSetup.taskManager, + interval: cloudSecurityMetringTaskProperties.interval, + }); return {}; } diff --git a/x-pack/plugins/security_solution_serverless/server/task_manager/usage_reporting_task.ts b/x-pack/plugins/security_solution_serverless/server/task_manager/usage_reporting_task.ts index 322ef2f32b0d972..0218ccf41c1ee7f 100644 --- a/x-pack/plugins/security_solution_serverless/server/task_manager/usage_reporting_task.ts +++ b/x-pack/plugins/security_solution_serverless/server/task_manager/usage_reporting_task.ts @@ -6,79 +6,71 @@ */ import type { Response } from 'node-fetch'; - -import type { CoreSetup, ElasticsearchClient, Logger, LoggerFactory } from '@kbn/core/server'; -import type { - ConcreteTaskInstance, - TaskManagerSetupContract, - TaskManagerStartContract, -} from '@kbn/task-manager-plugin/server'; +import type { CoreSetup, Logger } from '@kbn/core/server'; +import type { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; +import type { CloudSetup } from '@kbn/cloud-plugin/server'; import { throwUnrecoverableError } from '@kbn/task-manager-plugin/server'; - -import type { UsageRecord } from '../types'; import { usageReportingService } from '../common/services'; +import type { + MeteringCallback, + SecurityUsageReportingTaskStartContract, + SecurityUsageReportingTaskSetupContract, +} from '../types'; const SCOPE = ['serverlessSecurity']; const TIMEOUT = '1m'; export const VERSION = '1.0.0'; -type MeteringCallback = (metringCallbackInput: MeteringCallbackInput) => UsageRecord[]; - -export interface MeteringCallbackInput { - esClient: ElasticsearchClient; - lastSuccessfulReport: Date; -} - -export interface CloudSecurityUsageReportingTaskSetupContract { - taskType: string; - taskTitle: string; - meteringCallback: MeteringCallback; - logFactory: LoggerFactory; - core: CoreSetup; - taskManager: TaskManagerSetupContract; -} - -export interface SecurityMetadataTaskStartContract { - taskType: string; - interval: string; - version: string; - taskManager: TaskManagerStartContract; -} - export class SecurityUsageReportingTask { - private logger: Logger; private wasStarted: boolean = false; + private cloudSetup: CloudSetup; + private taskType: string; + private taskId: string; + private version: string; + private logger: Logger; - constructor(setupContract: CloudSecurityUsageReportingTaskSetupContract) { - const { taskType, taskTitle, logFactory, core, taskManager, meteringCallback } = setupContract; - - this.logger = logFactory.get(this.getTaskId(taskType)); - taskManager.registerTaskDefinitions({ - [taskType]: { - title: taskTitle, - timeout: TIMEOUT, - createTaskRunner: ({ taskInstance }: { taskInstance: ConcreteTaskInstance }) => { - return { - run: async () => { - return this.runTask(taskInstance, core, meteringCallback); - }, - // TODO - cancel: async () => {}, - }; + constructor(setupContract: SecurityUsageReportingTaskSetupContract) { + const { + core, + logFactory, + taskManager, + cloudSetup, + taskType, + taskTitle, + version, + meteringCallback, + } = setupContract; + + this.cloudSetup = cloudSetup; + this.taskType = taskType; + this.version = version; + this.taskId = this.getTaskId(taskType, version); + this.logger = logFactory.get(this.taskId); + + try { + taskManager.registerTaskDefinitions({ + [taskType]: { + title: taskTitle, + timeout: TIMEOUT, + createTaskRunner: ({ taskInstance }: { taskInstance: ConcreteTaskInstance }) => { + return { + run: async () => { + return this.runTask(taskInstance, core, meteringCallback); + }, + cancel: async () => {}, + }; + }, }, - }, - }); + }); + this.logger.info(`Scheduled task successfully ${taskTitle}`); + } catch (err) { + this.logger.error(`Failed to setup task ${taskType}, ${err} `); + } } - public start = async ({ - taskManager, - taskType, - interval, - version, - }: SecurityMetadataTaskStartContract) => { + public start = async ({ taskManager, interval }: SecurityUsageReportingTaskStartContract) => { if (!taskManager) { - this.logger.error('missing required service during start'); return; } @@ -86,8 +78,8 @@ export class SecurityUsageReportingTask { try { await taskManager.ensureScheduled({ - id: this.getTaskId(taskType), - taskType, + id: this.taskId, + taskType: this.taskType, scope: SCOPE, schedule: { interval, @@ -95,7 +87,7 @@ export class SecurityUsageReportingTask { state: { lastSuccessfulReport: null, }, - params: { version }, + params: { version: this.version }, }); } catch (e) { this.logger.debug(`Error scheduling task, received ${e.message}`); @@ -112,27 +104,47 @@ export class SecurityUsageReportingTask { this.logger.debug('[runTask()] Aborted. Task not started yet'); return; } - // Check that this task is current - if (taskInstance.id !== this.getTaskId(taskInstance.taskType)) { + if (taskInstance.id !== this.taskId) { // old task, die throwUnrecoverableError(new Error('Outdated task version')); } const [{ elasticsearch }] = await core.getStartServices(); - const esClient = elasticsearch.client.asInternalUser; + const lastSuccessfulReport = taskInstance.state.lastSuccessfulReport; - const usageRecords = meteringCallback({ esClient, lastSuccessfulReport }); + const usageRecords = await meteringCallback({ + esClient, + cloudSetup: this.cloudSetup, + logger: this.logger, + taskId: this.taskId, + lastSuccessfulReport, + }); + + this.logger.debug(`received usage records: ${JSON.stringify(usageRecords)}`); let usageReportResponse: Response | undefined; - try { - usageReportResponse = await usageReportingService.reportUsage(usageRecords); - } catch (e) { - this.logger.warn(JSON.stringify(e)); + if (usageRecords.length !== 0) { + try { + usageReportResponse = await usageReportingService.reportUsage(usageRecords); + + if (!usageReportResponse.ok) { + const errorResponse = await usageReportResponse.json(); + this.logger.error(`API error ${usageReportResponse.status}, ${errorResponse}`); + return; + } + + this.logger.info( + `usage records report was sent successfully: ${usageReportResponse.status}, ${usageReportResponse.statusText}` + ); + } catch (err) { + this.logger.error(`Failed to send usage records report ${JSON.stringify(err)} `); + } } + const state = { lastSuccessfulReport: usageReportResponse?.status === 201 ? new Date() : taskInstance.state.lastSuccessfulReport, @@ -140,7 +152,7 @@ export class SecurityUsageReportingTask { return { state }; }; - private getTaskId = (taskType: string): string => { - return `${taskType}:${VERSION}`; + private getTaskId = (taskType: string, version: string): string => { + return `${taskType}:${version}`; }; } diff --git a/x-pack/plugins/security_solution_serverless/server/types.ts b/x-pack/plugins/security_solution_serverless/server/types.ts index e107a32b49335ce..e3e3ad84b1d5e0d 100644 --- a/x-pack/plugins/security_solution_serverless/server/types.ts +++ b/x-pack/plugins/security_solution_serverless/server/types.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { CoreSetup, ElasticsearchClient, Logger, LoggerFactory } from '@kbn/core/server'; import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import type { PluginSetupContract, PluginStartContract } from '@kbn/features-plugin/server'; import type { @@ -12,9 +12,10 @@ import type { PluginStart as SecuritySolutionPluginStart, } from '@kbn/security-solution-plugin/server'; import type { - TaskManagerSetupContract as TaskManagerPluginSetup, - TaskManagerStartContract as TaskManagerPluginStart, + TaskManagerSetupContract, + TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; +import type { CloudSetup } from '@kbn/cloud-plugin/server'; import type { SecuritySolutionEssPluginSetup } from '@kbn/security-solution-ess/server'; import type { MlPluginSetup } from '@kbn/ml-plugin/server'; @@ -30,14 +31,15 @@ export interface SecuritySolutionServerlessPluginSetupDeps { securitySolutionEss: SecuritySolutionEssPluginSetup; features: PluginSetupContract; ml: MlPluginSetup; - taskManager: TaskManagerPluginSetup; + taskManager: TaskManagerSetupContract; + cloudSetup: CloudSetup; } export interface SecuritySolutionServerlessPluginStartDeps { security: SecurityPluginStart; securitySolution: SecuritySolutionPluginStart; features: PluginStartContract; - taskManager: TaskManagerPluginStart; + taskManager: TaskManagerStartContract; } export interface UsageRecord { @@ -60,5 +62,47 @@ export interface UsageMetrics { export interface UsageSource { id: string; instance_group_id: string; - instance_group_type: string; + instance_group_type?: string; // not seems part of step 1 fields https://github.com/elastic/mx-team/blob/main/teams/billing/services/usage_record_schema_v2.md +} + +export interface SecurityUsageReportingTaskSetupContract { + core: CoreSetup; + logFactory: LoggerFactory; + taskManager: TaskManagerSetupContract; + cloudSetup: CloudSetup; + taskType: string; + taskTitle: string; + version: string; + meteringCallback: MeteringCallback; +} + +export interface SecurityUsageReportingTaskStartContract { + taskManager: TaskManagerStartContract; + interval: string; +} + +export type MeteringCallback = ( + metringCallbackInput: MeteringCallbackInput +) => Promise; + +export interface MeteringCallbackInput { + esClient: ElasticsearchClient; + cloudSetup: CloudSetup; + logger: Logger; + taskId: string; + lastSuccessfulReport: Date; +} + +export interface CloudSecurityMeteringCallbackInput + extends Omit { + projectId: string; +} + +export interface MetringTaskProperties { + taskType: string; + taskTitle: string; + meteringCallback: MeteringCallback; + interval: string; + periodSeconds: number; + version: string; } diff --git a/x-pack/plugins/security_solution_serverless/tsconfig.json b/x-pack/plugins/security_solution_serverless/tsconfig.json index 30ecd2e9655b272..cce3249926fee32 100644 --- a/x-pack/plugins/security_solution_serverless/tsconfig.json +++ b/x-pack/plugins/security_solution_serverless/tsconfig.json @@ -11,9 +11,7 @@ "server/**/*.ts", "../../../typings/**/*" ], - "exclude": [ - "target/**/*" - ], + "exclude": ["target/**/*"], "kbn_references": [ "@kbn/core", "@kbn/config-schema", @@ -32,6 +30,8 @@ "@kbn/features-plugin", "@kbn/ml-plugin", "@kbn/kibana-utils-plugin", - "@kbn/task-manager-plugin" + "@kbn/task-manager-plugin", + "@kbn/cloud-plugin", + "@kbn/cloud-security-posture-plugin" ] } From 95702ac6445ef7843e01f67d3b2887ac3e0d260f Mon Sep 17 00:00:00 2001 From: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> Date: Tue, 25 Jul 2023 12:49:26 +0200 Subject: [PATCH 10/29] [Textbased] Lens integration - move `updateAll` callback to middleware (#162165) ## Summary There are 2 things refactored in this PR: 1. To make the updates from the config panel update the chart in discover, we have to run the `onUpdateCb` function in all places where the state changes in Lens. The problem is that when user adds a new feature to Lens, this is a potential source of sync bugs. We cannot test this behaviour with the way it's written now to avoid these bugs. My approach here changes the updates to a running a custom middleware every time the store state updates. I had to exclude some initialization actions to not end up in infinite loop updates (there's probably a better approach instead of excluding I haven't thought of yet). Another argument to do it this way is a performance improvement inside Lens component where we had to sometimes get all the store to make an `onUpdateCb` call. 2. the `useChartConfigPanel` hook should not really be a hook but a component as it is a component (returns JSX.Element, displays UI based on props) so I refactored it to `ChartConfigPanel`. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../public/__mocks__/services.tsx | 4 +- .../unified_histogram/public/chart/chart.tsx | 32 +++---- .../public/chart/chart_config_panel.test.tsx | 70 +++++++++++++++ ...onfig_panel.tsx => chart_config_panel.tsx} | 10 ++- .../hooks/use_chart_config_panel.test.tsx | 66 -------------- x-pack/plugins/lens/public/app_plugin/app.tsx | 3 +- .../lens/public/app_plugin/lens_top_nav.tsx | 3 +- .../lens/public/app_plugin/mounter.tsx | 12 +-- .../get_edit_lens_configuration.tsx | 69 ++++++++------- .../lens_configuration_flyout.tsx | 2 - .../config_panel/config_panel.test.tsx | 9 +- .../config_panel/config_panel.tsx | 59 +++---------- .../editor_frame/config_panel/types.ts | 1 - .../editor_frame/editor_frame.test.tsx | 7 +- .../workspace_panel/workspace_panel.test.tsx | 2 +- .../workspace_panel_wrapper.tsx | 14 +-- .../lens/public/embeddable/embeddable.tsx | 2 +- .../lens/public/mocks/lens_plugin_mock.tsx | 4 +- x-pack/plugins/lens/public/plugin.ts | 8 +- .../context_middleware/index.test.ts | 18 ++-- .../context_middleware/index.ts | 4 +- .../subscribe_to_external_context.ts | 6 +- .../public/state_management/index.test.ts | 86 +++++++++++++++++++ .../lens/public/state_management/index.ts | 29 +++++-- .../init_middleware/load_initial.ts | 6 +- .../public/state_management/lens_slice.ts | 33 ++++++- .../state_management/optimizing_middleware.ts | 26 +++++- .../lens/public/state_management/types.ts | 5 -- 28 files changed, 350 insertions(+), 240 deletions(-) create mode 100644 src/plugins/unified_histogram/public/chart/chart_config_panel.test.tsx rename src/plugins/unified_histogram/public/chart/{hooks/use_chart_config_panel.tsx => chart_config_panel.tsx} (92%) delete mode 100644 src/plugins/unified_histogram/public/chart/hooks/use_chart_config_panel.test.tsx create mode 100644 x-pack/plugins/lens/public/state_management/index.test.ts diff --git a/src/plugins/unified_histogram/public/__mocks__/services.tsx b/src/plugins/unified_histogram/public/__mocks__/services.tsx index 6b6e5a7f468647b..b7efb79941412ff 100644 --- a/src/plugins/unified_histogram/public/__mocks__/services.tsx +++ b/src/plugins/unified_histogram/public/__mocks__/services.tsx @@ -33,7 +33,9 @@ export const unifiedHistogramServicesMock = { suggestions: jest.fn(() => allSuggestionsMock), }; }), - EditLensConfigPanelApi: jest.fn().mockResolvedValue(Lens Config Panel Component), + EditLensConfigPanelApi: jest + .fn() + .mockResolvedValue(() => Lens Config Panel Component), }, storage: { get: jest.fn(), diff --git a/src/plugins/unified_histogram/public/chart/chart.tsx b/src/plugins/unified_histogram/public/chart/chart.tsx index 907ec70aa3b6997..ba6ffbaf149febc 100644 --- a/src/plugins/unified_histogram/public/chart/chart.tsx +++ b/src/plugins/unified_histogram/public/chart/chart.tsx @@ -42,7 +42,7 @@ import { useTotalHits } from './hooks/use_total_hits'; import { useRequestParams } from './hooks/use_request_params'; import { useChartStyles } from './hooks/use_chart_styles'; import { useChartActions } from './hooks/use_chart_actions'; -import { useChartConfigPanel } from './hooks/use_chart_config_panel'; +import { ChartConfigPanel } from './chart_config_panel'; import { getLensAttributes } from './utils/get_lens_attributes'; import { useRefetch } from './hooks/use_refetch'; import { useEditVisualization } from './hooks/use_edit_visualization'; @@ -220,19 +220,6 @@ export function Chart({ ] ); - const ChartConfigPanel = useChartConfigPanel({ - services, - lensAttributesContext, - dataView, - lensTablesAdapter, - currentSuggestion, - isFlyoutVisible, - setIsFlyoutVisible, - isPlainRecord, - query: originalQuery, - onSuggestionChange, - }); - const onSuggestionSelectorChange = useCallback( (s: Suggestion | undefined) => { onSuggestionChange?.(s); @@ -455,7 +442,22 @@ export function Chart({ isSaveable={false} /> )} - {isFlyoutVisible && ChartConfigPanel} + {isFlyoutVisible && ( + + )} ); } diff --git a/src/plugins/unified_histogram/public/chart/chart_config_panel.test.tsx b/src/plugins/unified_histogram/public/chart/chart_config_panel.test.tsx new file mode 100644 index 000000000000000..710666ac6637b13 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/chart_config_panel.test.tsx @@ -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 React from 'react'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import { render } from '@testing-library/react'; +import { act } from 'react-dom/test-utils'; +import { setTimeout } from 'timers/promises'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { unifiedHistogramServicesMock } from '../__mocks__/services'; +import { lensTablesAdapterMock } from '../__mocks__/lens_table_adapter'; +import { ChartConfigPanel } from './chart_config_panel'; +import type { LensAttributesContext } from './utils/get_lens_attributes'; + +describe('ChartConfigPanel', () => { + it('should return a jsx element to edit the visualization', async () => { + const lensAttributes = { + visualizationType: 'lnsXY', + title: 'test', + } as TypedLensByValueInput['attributes']; + const { container } = render( + + ); + await act(() => setTimeout(0)); + expect(container).not.toBeEmptyDOMElement(); + }); + + it('should return null if not in text based mode', async () => { + const lensAttributes = { + visualizationType: 'lnsXY', + title: 'test', + } as TypedLensByValueInput['attributes']; + const { container } = render( + + ); + await act(() => setTimeout(0)); + expect(container).toBeEmptyDOMElement(); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/hooks/use_chart_config_panel.tsx b/src/plugins/unified_histogram/public/chart/chart_config_panel.tsx similarity index 92% rename from src/plugins/unified_histogram/public/chart/hooks/use_chart_config_panel.tsx rename to src/plugins/unified_histogram/public/chart/chart_config_panel.tsx index c8b70c043fcdc50..c3faacd5b9a404d 100644 --- a/src/plugins/unified_histogram/public/chart/hooks/use_chart_config_panel.tsx +++ b/src/plugins/unified_histogram/public/chart/chart_config_panel.tsx @@ -12,10 +12,10 @@ import type { Suggestion } from '@kbn/lens-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { Datatable } from '@kbn/expressions-plugin/common'; -import type { UnifiedHistogramServices } from '../../types'; -import type { LensAttributesContext } from '../utils/get_lens_attributes'; +import type { UnifiedHistogramServices } from '../types'; +import type { LensAttributesContext } from './utils/get_lens_attributes'; -export function useChartConfigPanel({ +export function ChartConfigPanel({ services, lensAttributesContext, dataView, @@ -49,7 +49,9 @@ export function useChartConfigPanel({ ...(datasourceState && { datasourceState }), ...(visualizationState && { visualizationState }), } as Suggestion; - onSuggestionChange?.(updatedSuggestion); + if (!isEqual(updatedSuggestion, currentSuggestion)) { + onSuggestionChange?.(updatedSuggestion); + } }, [currentSuggestion, onSuggestionChange] ); diff --git a/src/plugins/unified_histogram/public/chart/hooks/use_chart_config_panel.test.tsx b/src/plugins/unified_histogram/public/chart/hooks/use_chart_config_panel.test.tsx deleted file mode 100644 index 5f0d4b17e80db4d..000000000000000 --- a/src/plugins/unified_histogram/public/chart/hooks/use_chart_config_panel.test.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 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 { TypedLensByValueInput } from '@kbn/lens-plugin/public'; -import { renderHook } from '@testing-library/react-hooks'; -import { act } from 'react-test-renderer'; -import { setTimeout } from 'timers/promises'; -import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield'; -import { unifiedHistogramServicesMock } from '../../__mocks__/services'; -import { lensTablesAdapterMock } from '../../__mocks__/lens_table_adapter'; -import { useChartConfigPanel } from './use_chart_config_panel'; -import type { LensAttributesContext } from '../utils/get_lens_attributes'; - -describe('useChartConfigPanel', () => { - it('should return a jsx element to edit the visualization', async () => { - const lensAttributes = { - visualizationType: 'lnsXY', - title: 'test', - } as TypedLensByValueInput['attributes']; - const hook = renderHook(() => - useChartConfigPanel({ - services: unifiedHistogramServicesMock, - dataView: dataViewWithTimefieldMock, - lensAttributesContext: { - attributes: lensAttributes, - } as unknown as LensAttributesContext, - isFlyoutVisible: true, - setIsFlyoutVisible: jest.fn(), - isPlainRecord: true, - lensTablesAdapter: lensTablesAdapterMock, - query: { - sql: 'Select * from test', - }, - }) - ); - await act(() => setTimeout(0)); - expect(hook.result.current).toBeDefined(); - expect(hook.result.current).not.toBeNull(); - }); - - it('should return null if not in text based mode', async () => { - const lensAttributes = { - visualizationType: 'lnsXY', - title: 'test', - } as TypedLensByValueInput['attributes']; - const hook = renderHook(() => - useChartConfigPanel({ - services: unifiedHistogramServicesMock, - dataView: dataViewWithTimefieldMock, - lensAttributesContext: { - attributes: lensAttributes, - } as unknown as LensAttributesContext, - isFlyoutVisible: true, - setIsFlyoutVisible: jest.fn(), - isPlainRecord: false, - }) - ); - await act(() => setTimeout(0)); - expect(hook.result.current).toBeNull(); - }); -}); diff --git a/x-pack/plugins/lens/public/app_plugin/app.tsx b/x-pack/plugins/lens/public/app_plugin/app.tsx index 47962ad4e2f2ab9..beff6ee8525d087 100644 --- a/x-pack/plugins/lens/public/app_plugin/app.tsx +++ b/x-pack/plugins/lens/public/app_plugin/app.tsx @@ -26,7 +26,6 @@ import { useLensSelector, useLensDispatch, LensAppState, - DispatchSetState, selectSavedObjectFormat, updateIndexPatterns, updateDatasourceState, @@ -99,7 +98,7 @@ export function App({ const saveAndExit = useRef<() => void>(); const dispatch = useLensDispatch(); - const dispatchSetState: DispatchSetState = useCallback( + const dispatchSetState = useCallback( (state: Partial) => dispatch(setState(state)), [dispatch] ); diff --git a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx index 35346b4cdabd0ab..dc4707a809bc923 100644 --- a/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx +++ b/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx @@ -25,7 +25,6 @@ import { useLensSelector, useLensDispatch, LensAppState, - DispatchSetState, switchAndCleanDatasource, } from '../state_management'; import { @@ -314,7 +313,7 @@ export const LensTopNavMenu = ({ } = useLensSelector((state) => state.lens); const dispatch = useLensDispatch(); - const dispatchSetState: DispatchSetState = React.useCallback( + const dispatchSetState = React.useCallback( (state: Partial) => dispatch(setState(state)), [dispatch] ); diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index af53a34b2edc052..0742e48882748b9 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -6,7 +6,6 @@ */ import React, { FC, useCallback, useEffect, useState, useMemo } from 'react'; -import { PreloadedState } from '@reduxjs/toolkit'; import { AppMountParameters, CoreSetup, CoreStart } from '@kbn/core/public'; import { FormattedMessage, I18nProvider } from '@kbn/i18n-react'; import { RouteComponentProps } from 'react-router-dom'; @@ -48,10 +47,9 @@ import { navigateAway, LensRootStore, loadInitial, - LensAppState, - LensState, + setState, } from '../state_management'; -import { getPreloadedState, setState } from '../state_management/lens_slice'; +import { getPreloadedState } from '../state_management/lens_slice'; import { getLensInspectorService } from '../lens_inspector_service'; import { LensAppLocator, @@ -276,9 +274,7 @@ export async function mountApp( initialContext, initialStateFromLocator, }; - const lensStore: LensRootStore = makeConfigureStore(storeDeps, { - lens: getPreloadedState(storeDeps) as LensAppState, - } as unknown as PreloadedState); + const lensStore: LensRootStore = makeConfigureStore(storeDeps); const EditorRenderer = React.memo( (props: { id?: string; history: History; editByValue?: boolean }) => { @@ -322,7 +318,7 @@ export async function mountApp( data.query.filterManager.setAppFilters([]); data.query.queryString.clearQuery(); } - lensStore.dispatch(setState(getPreloadedState(storeDeps) as LensAppState)); + lensStore.dispatch(setState(getPreloadedState(storeDeps))); lensStore.dispatch(loadInitial({ redirectCallback, initialInput, history: props.history })); }, [initialInput, props.history, redirectCallback]); useEffect(() => { diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx index 1ce4a777f952048..fe1e504637a669c 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx @@ -5,30 +5,23 @@ * 2.0. */ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { EuiFlyout, EuiLoadingSpinner, EuiOverlayMask } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Provider } from 'react-redux'; -import { PreloadedState } from '@reduxjs/toolkit'; +import { MiddlewareAPI, Dispatch, Action } from '@reduxjs/toolkit'; import { css } from '@emotion/react'; import type { CoreStart } from '@kbn/core/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { isEqual } from 'lodash'; import type { LensPluginStartDependencies } from '../../../plugin'; -import { - makeConfigureStore, - LensRootStore, - LensAppState, - LensState, - loadInitial, -} from '../../../state_management'; -import { getPreloadedState } from '../../../state_management/lens_slice'; +import { makeConfigureStore, LensRootStore, loadInitial } from '../../../state_management'; import { generateId } from '../../../id_generator'; import type { DatasourceMap, VisualizationMap } from '../../../types'; import { LensEditConfigurationFlyout, type EditConfigPanelProps, } from './lens_configuration_flyout'; -import type { LensAppServices } from '../../types'; export type EditLensConfigurationProps = Omit< EditConfigPanelProps, @@ -43,12 +36,39 @@ function LoadingSpinnerWithOverlay() { ); } -export function getEditLensConfiguration( +type UpdaterType = (datasourceState: unknown, visualizationState: unknown) => void; + +const updatingMiddleware = + (updater: UpdaterType) => (store: MiddlewareAPI) => (next: Dispatch) => (action: Action) => { + const { + datasourceStates: prevDatasourceStates, + visualization: prevVisualization, + activeDatasourceId: prevActiveDatasourceId, + } = store.getState().lens; + next(action); + const { datasourceStates, visualization, activeDatasourceId } = store.getState().lens; + if ( + !isEqual(prevDatasourceStates, datasourceStates) || + !isEqual(prevVisualization, visualization) || + prevActiveDatasourceId !== activeDatasourceId + ) { + updater(datasourceStates[activeDatasourceId].state, visualization.state); + } + }; + +export async function getEditLensConfiguration( coreStart: CoreStart, startDependencies: LensPluginStartDependencies, visualizationMap?: VisualizationMap, datasourceMap?: DatasourceMap ) { + const { getLensServices, getLensAttributeService } = await import('../../../async_services'); + const lensServices = await getLensServices( + coreStart, + startDependencies, + getLensAttributeService(coreStart, startDependencies) + ); + return ({ attributes, dataView, @@ -59,23 +79,6 @@ export function getEditLensConfiguration( adaptersTables, panelId, }: EditLensConfigurationProps) => { - const [lensServices, setLensServices] = useState(); - useEffect(() => { - async function loadLensService() { - const { getLensServices, getLensAttributeService } = await import( - '../../../async_services' - ); - const lensServicesT = await getLensServices( - coreStart, - startDependencies, - getLensAttributeService(coreStart, startDependencies) - ); - - setLensServices(lensServicesT); - } - loadLensService(); - }, []); - if (!lensServices || !datasourceMap || !visualizationMap || !dataView.id) { return ; } @@ -89,9 +92,11 @@ export function getEditLensConfiguration( ? datasourceState.initialContext : undefined, }; - const lensStore: LensRootStore = makeConfigureStore(storeDeps, { - lens: getPreloadedState(storeDeps) as LensAppState, - } as unknown as PreloadedState); + const lensStore: LensRootStore = makeConfigureStore( + storeDeps, + undefined, + updatingMiddleware(updateAll) + ); lensStore.dispatch( loadInitial({ initialInput: { diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx index 24b84f7665c5a4e..4d7fd3bbf703195 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx @@ -93,7 +93,6 @@ export function LensEditConfigurationFlyout({ dataViews: startDependencies.dataViews, uiActions: startDependencies.uiActions, hideLayerHeader: datasourceId === 'textBased', - onUpdateStateCb: updateAll, }; return ( <> @@ -120,7 +119,6 @@ export function LensEditConfigurationFlyout({ diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx index 1d896d796edc1b8..c5ec748aa9bf099 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.test.tsx @@ -170,25 +170,18 @@ describe('ConfigPanel', () => { it('updates datasources and visualizations', async () => { const props = getDefaultProps(); - const onUpdateCbSpy = jest.fn(); - const newProps = { - ...props, - onUpdateStateCb: onUpdateCbSpy, - }; - const { instance, lensStore } = await prepareAndMountComponent(newProps); + const { instance, lensStore } = await prepareAndMountComponent(props); const { updateDatasource, updateAll } = instance.find(LayerPanel).props(); const newDatasourceState = 'updated'; updateDatasource('testDatasource', newDatasourceState); await waitMs(0); expect(lensStore.dispatch).toHaveBeenCalledTimes(1); - expect(onUpdateCbSpy).toHaveBeenCalled(); expect((lensStore.dispatch as jest.Mock).mock.calls[0][0].payload.newDatasourceState).toEqual( 'updated' ); updateAll('testDatasource', newDatasourceState, props.visualizationState); - expect(onUpdateCbSpy).toHaveBeenCalled(); // wait for one tick so async updater has a chance to trigger await waitMs(0); expect(lensStore.dispatch).toHaveBeenCalledTimes(3); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx index 523ce6dc856b829..2a7056c759fac3e 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx @@ -6,7 +6,6 @@ */ import React, { useMemo, memo, useCallback } from 'react'; -import { useStore } from 'react-redux'; import { EuiForm } from '@elastic/eui'; import { ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; import { isOfAggregateQueryType } from '@kbn/es-query'; @@ -14,7 +13,7 @@ import { UPDATE_FILTER_REFERENCES_ACTION, UPDATE_FILTER_REFERENCES_TRIGGER, } from '@kbn/unified-search-plugin/public'; -import { isEqual } from 'lodash'; + import { DragDropIdentifier, DropType } from '@kbn/dom-drag-drop'; import { changeIndexPattern, @@ -58,8 +57,7 @@ export function LayerPanels( activeVisualization: Visualization; } ) { - const lensStore = useStore(); - const { activeVisualization, datasourceMap, indexPatternService, onUpdateStateCb } = props; + const { activeVisualization, datasourceMap, indexPatternService } = props; const { activeDatasourceId, visualization, datasourceStates, query } = useLensSelector( (state) => state.lens ); @@ -81,31 +79,19 @@ export function LayerPanels( newState, }) ); - if (onUpdateStateCb && activeDatasourceId) { - const dsState = datasourceStates[activeDatasourceId].state; - onUpdateStateCb?.(dsState, newState); - } }, - [activeDatasourceId, activeVisualization.id, datasourceStates, dispatchLens, onUpdateStateCb] + [activeVisualization.id, dispatchLens] ); const updateDatasource = useMemo( () => (datasourceId: string | undefined, newState: unknown, dontSyncLinkedDimensions?: boolean) => { if (datasourceId) { - const newDatasourceState = - typeof newState === 'function' - ? newState(datasourceStates[datasourceId].state) - : newState; - - if (isEqual(newDatasourceState, datasourceStates[datasourceId].state)) { - return; - } - - onUpdateStateCb?.(newDatasourceState, visualization.state); - dispatchLens( updateDatasourceState({ - newDatasourceState, + newDatasourceState: + typeof newState === 'function' + ? newState(datasourceStates[datasourceId].state) + : newState, datasourceId, clearStagedPreview: false, dontSyncLinkedDimensions, @@ -113,7 +99,7 @@ export function LayerPanels( ); } }, - [dispatchLens, onUpdateStateCb, visualization.state, datasourceStates] + [dispatchLens, datasourceStates] ); const updateDatasourceAsync = useMemo( () => (datasourceId: string | undefined, newState: unknown) => { @@ -148,8 +134,6 @@ export function LayerPanels( ? newVisualizationState(visualization.state) : newVisualizationState; - onUpdateStateCb?.(newDsState, newVisState); - dispatchLens( updateVisualizationState({ visualizationId: activeVisualization.id, @@ -166,7 +150,7 @@ export function LayerPanels( ); }, 0); }, - [dispatchLens, onUpdateStateCb, visualization.state, datasourceStates, activeVisualization.id] + [dispatchLens, visualization.state, datasourceStates, activeVisualization.id] ); const toggleFullscreen = useCallback(() => { @@ -207,24 +191,15 @@ export function LayerPanels( layerIds, }) ); - if (activeDatasourceId && onUpdateStateCb) { - const newState = lensStore.getState().lens; - onUpdateStateCb( - newState.datasourceStates[activeDatasourceId].state, - newState.visualization.state - ); - } + removeLayerRef(layerToRemoveId); }, [ - activeDatasourceId, activeVisualization.id, datasourceMap, datasourceStates, dispatchLens, layerIds, - lensStore, - onUpdateStateCb, props.framePublicAPI.datasourceLayers, props.uiActions, removeLayerRef, @@ -267,13 +242,6 @@ export function LayerPanels( dispatchLens(addLayerAction({ layerId, layerType, extraArg, ignoreInitialValues })); - if (activeDatasourceId && onUpdateStateCb) { - const newState = lensStore.getState().lens; - onUpdateStateCb( - newState.datasourceStates[activeDatasourceId].state, - newState.visualization.state - ); - } setNextFocusedLayerId(layerId); }; @@ -355,13 +323,6 @@ export function LayerPanels( const datasourcePublicAPI = props.framePublicAPI.datasourceLayers?.[layerId]; const datasourceId = datasourcePublicAPI?.datasourceId; dispatchLens(removeDimension({ ...dimensionProps, datasourceId })); - if (datasourceId && onUpdateStateCb) { - const newState = lensStore.getState().lens; - onUpdateStateCb( - newState.datasourceStates[datasourceId].state, - newState.visualization.state - ); - } }} toggleFullscreen={toggleFullscreen} indexPatternService={indexPatternService} diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts index 994ba4b1b96cd58..9b1ed7fde93825b 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts @@ -29,7 +29,6 @@ export interface ConfigPanelWrapperProps { uiActions: UiActionsStart; getUserMessages?: UserMessagesGetter; hideLayerHeader?: boolean; - onUpdateStateCb?: (datasourceState: unknown, visualizationState: unknown) => void; } export interface LayerPanelProps { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx index 988bb0bb655921e..3d90273ef0d1439 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx @@ -383,15 +383,16 @@ describe('editor_frame', () => { hasDefaultTimeField: jest.fn(() => true), }; mockDatasource.getPublicAPI.mockReturnValue(updatedPublicAPI); + mockVisualization.getConfiguration.mockClear(); const setDatasourceState = (mockDatasource.DataPanelComponent as jest.Mock).mock.calls[0][0] .setState; act(() => { - setDatasourceState({}); + setDatasourceState('newState'); }); - expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(3); - expect(mockVisualization.getConfiguration).toHaveBeenLastCalledWith( + expect(mockVisualization.getConfiguration).toHaveBeenCalledTimes(1); + expect(mockVisualization.getConfiguration).toHaveBeenCalledWith( expect.objectContaining({ frame: expect.objectContaining({ datasourceLayers: { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx index 5695d746d69a2bd..18d0833ed425086 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx @@ -798,7 +798,7 @@ describe('workspace_panel', () => { lensStore.dispatch( updateDatasourceState({ datasourceId: 'testDatasource', - newDatasourceState: {}, + newDatasourceState: 'newState', }) ); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx index 9469a903131bd38..ea2c8d27086fbc6 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx @@ -30,6 +30,7 @@ import { selectChangesApplied, applyChanges, selectAutoApplyEnabled, + selectVisualizationState, } from '../../../state_management'; import { WorkspaceTitle } from './title'; import { LensInspector } from '../../../lens_inspector_service'; @@ -52,13 +53,10 @@ export interface WorkspacePanelWrapperProps { export function VisualizationToolbar(props: { activeVisualization: Visualization | null; framePublicAPI: FramePublicAPI; - onUpdateStateCb?: (datasourceState: unknown, visualizationState: unknown) => void; }) { const dispatchLens = useLensDispatch(); - const { activeDatasourceId, visualization, datasourceStates } = useLensSelector( - (state) => state.lens - ); - const { activeVisualization, onUpdateStateCb } = props; + const visualization = useLensSelector(selectVisualizationState); + const { activeVisualization } = props; const setVisualizationState = useCallback( (newState: unknown) => { if (!activeVisualization) { @@ -70,12 +68,8 @@ export function VisualizationToolbar(props: { newState, }) ); - if (activeDatasourceId && onUpdateStateCb) { - const dsState = datasourceStates[activeDatasourceId].state; - onUpdateStateCb?.(dsState, newState); - } }, - [activeDatasourceId, datasourceStates, dispatchLens, activeVisualization, onUpdateStateCb] + [dispatchLens, activeVisualization] ); const ToolbarComponent = props.activeVisualization?.ToolbarComponent; diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index d586dd596f487e2..403ba51d72bc488 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -780,7 +780,7 @@ export class Embeddable async openConfingPanel(startDependencies: LensPluginStartDependencies) { const { getEditLensConfiguration } = await import('../async_services'); - const Component = getEditLensConfiguration( + const Component = await getEditLensConfiguration( this.deps.coreStart, startDependencies, this.deps.visualizationMap, diff --git a/x-pack/plugins/lens/public/mocks/lens_plugin_mock.tsx b/x-pack/plugins/lens/public/mocks/lens_plugin_mock.tsx index f526e46d8f5ec37..dbac941720b4d79 100644 --- a/x-pack/plugins/lens/public/mocks/lens_plugin_mock.tsx +++ b/x-pack/plugins/lens/public/mocks/lens_plugin_mock.tsx @@ -21,7 +21,9 @@ export const lensPluginMock = { SaveModalComponent: jest.fn(() => { return Lens Save Modal Component; }), - EditLensConfigPanelApi: jest.fn().mockResolvedValue(Lens Config Panel Component), + EditLensConfigPanelApi: jest + .fn() + .mockResolvedValue(() => Lens Config Panel Component), canUseEditor: jest.fn(() => true), navigateToPrefilledEditor: jest.fn(), getXyVisTypes: jest diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index 3f2559ce634bea3..14cd471a2a5bc2a 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -677,7 +677,13 @@ export class LensPlugin { this.editorFrameService!.loadVisualizations(), this.editorFrameService!.loadDatasources(), ]); - return getEditLensConfiguration(core, startDependencies, visualizationMap, datasourceMap); + const Component = await getEditLensConfiguration( + core, + startDependencies, + visualizationMap, + datasourceMap + ); + return Component; }, }; } diff --git a/x-pack/plugins/lens/public/state_management/context_middleware/index.test.ts b/x-pack/plugins/lens/public/state_management/context_middleware/index.test.ts index 19e40577acad6fe..24254f4469f54d0 100644 --- a/x-pack/plugins/lens/public/state_management/context_middleware/index.test.ts +++ b/x-pack/plugins/lens/public/state_management/context_middleware/index.test.ts @@ -57,7 +57,7 @@ describe('contextMiddleware', () => { }); const { next, invoke, store } = createMiddleware(data); const action = { - type: 'lens/setState', + type: 'lens/setExecutionContext', payload: { visualization: { state: {}, @@ -74,7 +74,7 @@ describe('contextMiddleware', () => { }, searchSessionId: 'sessionId-1', }, - type: 'lens/setState', + type: 'lens/setExecutionContext', }); expect(next).toHaveBeenCalledWith(action); }); @@ -92,7 +92,7 @@ describe('contextMiddleware', () => { }); const { next, invoke, store } = createMiddleware(data); const action = { - type: 'lens/setState', + type: 'lens/setExecutionContext', payload: { visualization: { state: {}, @@ -109,7 +109,7 @@ describe('contextMiddleware', () => { }, searchSessionId: 'sessionId-1', }, - type: 'lens/setState', + type: 'lens/setExecutionContext', }); expect(next).toHaveBeenCalledWith(action); }); @@ -136,7 +136,7 @@ describe('contextMiddleware', () => { // setState shouldn't trigger const setStateAction = { - type: 'lens/setState', + type: 'lens/setExecutionContext', payload: { visualization: { state: {}, @@ -146,14 +146,14 @@ describe('contextMiddleware', () => { }; invoke(setStateAction); expect(store.dispatch).not.toHaveBeenCalledWith( - expect.objectContaining({ type: 'lens/setState' }) + expect.objectContaining({ type: 'lens/setExecutionContext' }) ); // applyChanges should trigger const applyChangesAction = applyChanges(); invoke(applyChangesAction); expect(store.dispatch).toHaveBeenCalledWith( - expect.objectContaining({ type: 'lens/setState' }) + expect.objectContaining({ type: 'lens/setExecutionContext' }) ); }); }); @@ -171,7 +171,7 @@ describe('contextMiddleware', () => { }); const { next, invoke, store } = createMiddleware(data); const action = { - type: 'lens/setState', + type: 'lens/setExecutionContext', payload: { visualization: { state: {}, @@ -196,7 +196,7 @@ describe('contextMiddleware', () => { }); const { next, invoke, store } = createMiddleware(data); const action = { - type: 'lens/setState', + type: 'lens/setExecutionContext', payload: { visualization: { state: {}, diff --git a/x-pack/plugins/lens/public/state_management/context_middleware/index.ts b/x-pack/plugins/lens/public/state_management/context_middleware/index.ts index 7d1e6a0b48fbae4..f17863a25d42e8e 100644 --- a/x-pack/plugins/lens/public/state_management/context_middleware/index.ts +++ b/x-pack/plugins/lens/public/state_management/context_middleware/index.ts @@ -9,7 +9,7 @@ import { Dispatch, MiddlewareAPI, PayloadAction } from '@reduxjs/toolkit'; import moment from 'moment'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { - setState, + setExecutionContext, LensDispatch, LensStoreDeps, navigateAway, @@ -93,7 +93,7 @@ function updateTimeRange(data: DataPublicPluginStart, dispatch: LensDispatch) { // if the lag is significant, start a new session to clear the cache if (nowDiff > Math.max(timeRangeLength * TIME_LAG_PERCENTAGE_LIMIT, TIME_LAG_MIN_LIMIT)) { dispatch( - setState({ + setExecutionContext({ searchSessionId: data.search.session.start(), resolvedDateRange: getResolvedDateRange(timefilter), }) diff --git a/x-pack/plugins/lens/public/state_management/context_middleware/subscribe_to_external_context.ts b/x-pack/plugins/lens/public/state_management/context_middleware/subscribe_to_external_context.ts index abc3f388db5e9c3..3445e48df0a1b85 100644 --- a/x-pack/plugins/lens/public/state_management/context_middleware/subscribe_to_external_context.ts +++ b/x-pack/plugins/lens/public/state_management/context_middleware/subscribe_to_external_context.ts @@ -8,7 +8,7 @@ import { delay, finalize, switchMap, tap } from 'rxjs/operators'; import { debounce, isEqual } from 'lodash'; import { waitUntilNextSessionCompletes$, DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { setState, LensGetState, LensDispatch } from '..'; +import { setExecutionContext, LensGetState, LensDispatch } from '..'; import { getResolvedDateRange } from '../../utils'; /** @@ -21,14 +21,14 @@ export function subscribeToExternalContext( ) { const { query: queryService, search } = data; const { filterManager } = queryService; - const dispatchFromExternal = (searchSessionId = search.session.start()) => { const globalFilters = filterManager.getFilters(); const filters = isEqual(getState().lens.filters, globalFilters) ? null : { filters: globalFilters }; + dispatch( - setState({ + setExecutionContext({ searchSessionId, ...filters, resolvedDateRange: getResolvedDateRange(queryService.timefilter.timefilter), diff --git a/x-pack/plugins/lens/public/state_management/index.test.ts b/x-pack/plugins/lens/public/state_management/index.test.ts new file mode 100644 index 000000000000000..b38a9587eafdd85 --- /dev/null +++ b/x-pack/plugins/lens/public/state_management/index.test.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Action, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit'; +import { makeConfigureStore, onActiveDataChange, setExecutionContext } from '.'; +import { mockStoreDeps } from '../mocks'; +import { TableInspectorAdapter } from '../editor_frame_service/types'; +import { Filter } from '@kbn/es-query'; + +describe('state management initialization and middlewares', () => { + let store: ReturnType; + const updaterFn = jest.fn(); + const customMiddleware = jest.fn( + (updater) => (_store: MiddlewareAPI) => (next: Dispatch) => (action: Action) => { + next(action); + updater(action); + } + ); + beforeEach(() => { + store = makeConfigureStore(mockStoreDeps(), undefined, customMiddleware(updaterFn)); + store.dispatch = jest.fn(store.dispatch); + }); + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('customMiddleware', () => { + test('customMiddleware is initialized on store creation', () => { + expect(customMiddleware).toHaveBeenCalled(); + expect(updaterFn).not.toHaveBeenCalled(); + }); + test('customMiddleware is run on action dispatch', () => { + store.dispatch({ type: 'ANY_TYPE' }); + expect(updaterFn).toHaveBeenCalledWith({ type: 'ANY_TYPE' }); + }); + }); + + describe('optimizingMiddleware', () => { + test('state is updating when the activeData changes', () => { + expect(store.getState().lens.activeData).toEqual(undefined); + store.dispatch( + onActiveDataChange({ activeData: { id: 1 } as unknown as TableInspectorAdapter }) + ); + expect(store.getState().lens.activeData).toEqual({ id: 1 }); + // this is a bit convoluted - we are checking that the updaterFn has been called because it's called (as the next middleware) + // before the reducer function but we're actually interested in the reducer function being called that's further down the pipeline + expect(updaterFn).toHaveBeenCalledTimes(1); + store.dispatch( + onActiveDataChange({ activeData: { id: 2 } as unknown as TableInspectorAdapter }) + ); + expect(store.getState().lens.activeData).toEqual({ id: 2 }); + expect(updaterFn).toHaveBeenCalledTimes(2); + }); + test('state is not updating when the payload activeData is the same as in state', () => { + store.dispatch( + onActiveDataChange({ activeData: { id: 1 } as unknown as TableInspectorAdapter }) + ); + expect(store.getState().lens.activeData).toEqual({ id: 1 }); + expect(updaterFn).toHaveBeenCalledTimes(1); + store.dispatch( + onActiveDataChange({ activeData: { id: 1 } as unknown as TableInspectorAdapter }) + ); + expect(store.getState().lens.activeData).toEqual({ id: 1 }); + expect(updaterFn).toHaveBeenCalledTimes(1); + }); + test('state is updating when the execution context changes', () => { + expect(store.getState().lens.filters).toEqual([]); + expect(store.getState().lens.query).toEqual({ language: 'lucene', query: '' }); + expect(store.getState().lens.searchSessionId).toEqual(''); + store.dispatch( + setExecutionContext({ + filters: ['filter'] as unknown as Filter[], + query: { language: 'lucene', query: 'query' }, + searchSessionId: 'searchSessionId', + }) + ); + expect(store.getState().lens.filters).toEqual(['filter']); + expect(store.getState().lens.query).toEqual({ language: 'lucene', query: 'query' }); + expect(store.getState().lens.searchSessionId).toEqual('searchSessionId'); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/state_management/index.ts b/x-pack/plugins/lens/public/state_management/index.ts index 6bfa0744fa54ea7..6f170219df74479 100644 --- a/x-pack/plugins/lens/public/state_management/index.ts +++ b/x-pack/plugins/lens/public/state_management/index.ts @@ -5,10 +5,17 @@ * 2.0. */ -import { configureStore, getDefaultMiddleware, PreloadedState } from '@reduxjs/toolkit'; +import { + configureStore, + getDefaultMiddleware, + PreloadedState, + Action, + Dispatch, + MiddlewareAPI, +} from '@reduxjs/toolkit'; import { createLogger } from 'redux-logger'; import { useDispatch, useSelector, TypedUseSelectorHook } from 'react-redux'; -import { makeLensReducer, lensActions } from './lens_slice'; +import { makeLensReducer, lensActions, getPreloadedState } from './lens_slice'; import { LensState, LensStoreDeps } from './types'; import { initMiddleware } from './init_middleware'; import { optimizingMiddleware } from './optimizing_middleware'; @@ -19,7 +26,10 @@ export * from './selectors'; export const { loadInitial, + initEmpty, + initExisting, navigateAway, + setExecutionContext, setState, enableAutoApply, disableAutoApply, @@ -36,7 +46,6 @@ export const { switchAndCleanDatasource, updateIndexPatterns, setToggleFullscreen, - initEmpty, editVisualizationAction, removeLayers, removeOrClearLayer, @@ -50,9 +59,12 @@ export const { changeIndexPattern, } = lensActions; +type CustomMiddleware = (store: MiddlewareAPI) => (next: Dispatch) => (action: Action) => void; + export const makeConfigureStore = ( storeDeps: LensStoreDeps, - preloadedState: PreloadedState + preloadedState?: PreloadedState | undefined, + customMiddleware?: CustomMiddleware ) => { const middleware = [ ...getDefaultMiddleware({ @@ -70,10 +82,13 @@ export const makeConfigureStore = ( }, }), initMiddleware(storeDeps), - optimizingMiddleware(), contextMiddleware(storeDeps), fullscreenMiddleware(storeDeps), + optimizingMiddleware(), ]; + if (customMiddleware) { + middleware.push(customMiddleware); + } if (process.env.NODE_ENV === 'development') { middleware.push( createLogger({ @@ -88,7 +103,9 @@ export const makeConfigureStore = ( lens: makeLensReducer(storeDeps), }, middleware, - preloadedState, + preloadedState: preloadedState ?? { + lens: getPreloadedState(storeDeps), + }, }); }; diff --git a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts index 59e022345c60306..df7da58cfa5e792 100644 --- a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts +++ b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts @@ -9,7 +9,7 @@ import { cloneDeep } from 'lodash'; import { MiddlewareAPI } from '@reduxjs/toolkit'; import { i18n } from '@kbn/i18n'; import { History } from 'history'; -import { setState, initEmpty, LensStoreDeps } from '..'; +import { setState, initExisting, initEmpty, LensStoreDeps } from '..'; import { disableAutoApply, getPreloadedState } from '../lens_slice'; import { SharingSavedObjectProps } from '../../types'; import { LensEmbeddableInput, LensByReferenceInput } from '../../embeddable/embeddable'; @@ -171,7 +171,7 @@ export function loadInitial( const currentSessionId = initialStateFromLocator?.searchSessionId || data.search.session.getSessionId(); store.dispatch( - setState({ + initExisting({ isSaveable: true, filters: initialStateFromLocator.filters || data.query.filterManager.getFilters(), query: initialStateFromLocator.query || emptyState.query, @@ -331,7 +331,7 @@ export function loadInitial( }) => { const currentSessionId = data.search.session.getSessionId(); store.dispatch( - setState({ + initExisting({ isSaveable: true, sharingSavedObjectProps, filters: data.query.filterManager.getFilters(), diff --git a/x-pack/plugins/lens/public/state_management/lens_slice.ts b/x-pack/plugins/lens/public/state_management/lens_slice.ts index d90f0d7a2a05ef6..ffc22d68f9e4cc4 100644 --- a/x-pack/plugins/lens/public/state_management/lens_slice.ts +++ b/x-pack/plugins/lens/public/state_management/lens_slice.ts @@ -8,7 +8,7 @@ import { createAction, createReducer, current, PayloadAction } from '@reduxjs/toolkit'; import { VisualizeFieldContext } from '@kbn/ui-actions-plugin/public'; import { mapValues, uniq } from 'lodash'; -import { Query } from '@kbn/es-query'; +import { Filter, Query } from '@kbn/es-query'; import { History } from 'history'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import { EventAnnotationGroupConfig } from '@kbn/event-annotation-common'; @@ -27,7 +27,7 @@ import { getInitialDatasourceId, getResolvedDateRange, getRemoveOperation } from import type { DataViewsState, LensAppState, LensStoreDeps, VisualizationState } from './types'; import type { Datasource, Visualization } from '../types'; import { generateId } from '../id_generator'; -import type { LayerType } from '../../common/types'; +import type { DateRange, LayerType } from '../../common/types'; import { getVisualizeFieldSuggestions } from '../editor_frame_service/editor_frame/suggestion_helpers'; import type { FramePublicAPI, LensEditContextMapping, LensEditEvent } from '../types'; import { selectDataViews, selectFramePublicAPI } from './selectors'; @@ -113,7 +113,7 @@ export const getPreloadedState = ({ ? data.query.queryString.getDefaultQuery() : getQueryFromContext(initialContext, data); - const state = { + const state: LensAppState = { ...initialState, isLoading: true, // Do not use app-specific filters from previous app, @@ -124,7 +124,7 @@ export const getPreloadedState = ({ : 'searchFilters' in initialContext && initialContext.searchFilters ? initialContext.searchFilters : data.query.filterManager.getFilters(), - searchSessionId: data.search.session.getSessionId(), + searchSessionId: data.search.session.getSessionId() || '', resolvedDateRange: getResolvedDateRange(data.query.timefilter.timefilter), isLinkedToOriginatingApp: Boolean( embeddableEditorIncomingState?.originatingApp || @@ -140,7 +140,18 @@ export const getPreloadedState = ({ return state; }; +export interface SetExecutionContextPayload { + query?: Query; + filters?: Filter[]; + searchSessionId?: string; + resolvedDateRange?: DateRange; +} + export const setState = createAction>('lens/setState'); +export const setExecutionContext = createAction( + 'lens/setExecutionContext' +); +export const initExisting = createAction>('lens/initExisting'); export const onActiveDataChange = createAction<{ activeData: TableInspectorAdapter; }>('lens/onActiveDataChange'); @@ -268,7 +279,9 @@ export const registerLibraryAnnotationGroup = createAction<{ }>('lens/registerLibraryAnnotationGroup'); export const lensActions = { + initExisting, setState, + setExecutionContext, onActiveDataChange, setSaveable, enableAutoApply, @@ -312,6 +325,18 @@ export const makeLensReducer = (storeDeps: LensStoreDeps) => { ...payload, }; }, + [setExecutionContext.type]: (state, { payload }: PayloadAction) => { + return { + ...state, + ...payload, + }; + }, + [initExisting.type]: (state, { payload }: PayloadAction>) => { + return { + ...state, + ...payload, + }; + }, [onActiveDataChange.type]: ( state, { payload: { activeData } }: PayloadAction<{ activeData: TableInspectorAdapter }> diff --git a/x-pack/plugins/lens/public/state_management/optimizing_middleware.ts b/x-pack/plugins/lens/public/state_management/optimizing_middleware.ts index 9c8fe99c38aea24..7187419cb438b34 100644 --- a/x-pack/plugins/lens/public/state_management/optimizing_middleware.ts +++ b/x-pack/plugins/lens/public/state_management/optimizing_middleware.ts @@ -7,7 +7,8 @@ import { Dispatch, MiddlewareAPI, Action } from '@reduxjs/toolkit'; import { isEqual } from 'lodash'; -import { onActiveDataChange } from '.'; +import { onActiveDataChange, updateDatasourceState, setExecutionContext } from '.'; +import { SetExecutionContextPayload } from './lens_slice'; /** cancels updates to the store that don't change the state */ export const optimizingMiddleware = () => (store: MiddlewareAPI) => { @@ -16,7 +17,30 @@ export const optimizingMiddleware = () => (store: MiddlewareAPI) => { if (isEqual(store.getState().lens.activeData, action.payload.activeData)) { return; } + } else if (updateDatasourceState.match(action)) { + const { datasourceId, newDatasourceState } = action.payload; + const { datasourceStates } = store.getState().lens; + if (isEqual(datasourceStates[datasourceId].state, newDatasourceState)) { + return; + } + } else if (setExecutionContext.match(action)) { + const payloadKeys = Object.keys(action.payload); + const prevState = store.getState().lens; + const stateSliceToUpdate = payloadKeys.reduce( + (acc, currentKey) => { + return { + ...acc, + [currentKey]: prevState[currentKey], + }; + }, + {} + ); + + if (isEqual(action.payload, stateSliceToUpdate)) { + return; + } } + next(action); }; }; diff --git a/x-pack/plugins/lens/public/state_management/types.ts b/x-pack/plugins/lens/public/state_management/types.ts index 2ba00df37d73b42..c2d0e1ef2e386bc 100644 --- a/x-pack/plugins/lens/public/state_management/types.ts +++ b/x-pack/plugins/lens/public/state_management/types.ts @@ -67,11 +67,6 @@ export interface LensAppState extends EditorFrameState { annotationGroups: AnnotationGroups; } -export type DispatchSetState = (state: Partial) => { - payload: Partial; - type: string; -}; - export interface LensState { lens: LensAppState; } From c76b185323fa3de5e0c9068293569ac179686a43 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Tue, 25 Jul 2023 13:21:28 +0200 Subject: [PATCH 11/29] [uiSettings] use `refresh: false` instead of default `refresh: 'wait_for'` in create and update (#160278) ## Summary Close https://github.com/elastic/kibana/issues/159662 See explanation [here](https://github.com/elastic/kibana/issues/159662) --- .../src/clients/ui_settings_client.test.ts | 60 ++++++++++++++----- .../src/clients/ui_settings_client_common.ts | 2 +- .../clients/ui_settings_global_client.test.ts | 11 +++- .../create_or_upgrade_saved_config.test.ts | 6 +- .../create_or_upgrade_saved_config.ts | 2 +- .../src/actions/empty_kibana_index.ts | 1 + .../ui_settings/doc_missing.ts | 2 + 7 files changed, 63 insertions(+), 21 deletions(-) diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client.test.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client.test.ts index 2612c8778898bc5..b00517d259a48b9 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client.test.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client.test.ts @@ -64,7 +64,12 @@ describe('ui settings', () => { await uiSettings.setMany({ one: 'value' }); expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(savedObjectsClient.update).toHaveBeenCalledWith(TYPE, ID, { one: 'value' }); + expect(savedObjectsClient.update).toHaveBeenCalledWith( + TYPE, + ID, + { one: 'value' }, + { refresh: false } + ); }); it('updates several values in one operation', async () => { @@ -72,10 +77,15 @@ describe('ui settings', () => { await uiSettings.setMany({ one: 'value', another: 'val' }); expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(savedObjectsClient.update).toHaveBeenCalledWith(TYPE, ID, { - one: 'value', - another: 'val', - }); + expect(savedObjectsClient.update).toHaveBeenCalledWith( + TYPE, + ID, + { + one: 'value', + another: 'val', + }, + { refresh: false } + ); }); it('automatically creates the savedConfig if it is missing', async () => { @@ -159,9 +169,14 @@ describe('ui settings', () => { await uiSettings.set('one', 'value'); expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(savedObjectsClient.update).toHaveBeenCalledWith(TYPE, ID, { - one: 'value', - }); + expect(savedObjectsClient.update).toHaveBeenCalledWith( + TYPE, + ID, + { + one: 'value', + }, + { refresh: false } + ); }); it('validates value if a schema presents', async () => { @@ -202,7 +217,12 @@ describe('ui settings', () => { await uiSettings.remove('one'); expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(savedObjectsClient.update).toHaveBeenCalledWith(TYPE, ID, { one: null }); + expect(savedObjectsClient.update).toHaveBeenCalledWith( + TYPE, + ID, + { one: null }, + { refresh: false } + ); }); it('does not fail validation', async () => { @@ -246,7 +266,12 @@ describe('ui settings', () => { await uiSettings.removeMany(['one']); expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(savedObjectsClient.update).toHaveBeenCalledWith(TYPE, ID, { one: null }); + expect(savedObjectsClient.update).toHaveBeenCalledWith( + TYPE, + ID, + { one: null }, + { refresh: false } + ); }); it('updates several values in one operation', async () => { @@ -254,11 +279,16 @@ describe('ui settings', () => { await uiSettings.removeMany(['one', 'two', 'three']); expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(savedObjectsClient.update).toHaveBeenCalledWith(TYPE, ID, { - one: null, - two: null, - three: null, - }); + expect(savedObjectsClient.update).toHaveBeenCalledWith( + TYPE, + ID, + { + one: null, + two: null, + three: null, + }, + { refresh: false } + ); }); it('does not fail validation', async () => { diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client_common.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client_common.ts index 992a851db99fdc6..d52644a0e8bfe93 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client_common.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_client_common.ts @@ -129,7 +129,7 @@ export abstract class UiSettingsClientCommon extends BaseUiSettingsClient { autoCreateOrUpgradeIfMissing?: boolean; }) { try { - await this.savedObjectsClient.update(this.type, this.id, changes); + await this.savedObjectsClient.update(this.type, this.id, changes, { refresh: false }); } catch (error) { if (!SavedObjectsErrorHelpers.isNotFoundError(error) || !autoCreateOrUpgradeIfMissing) { throw error; diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_global_client.test.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_global_client.test.ts index 2e4988f20c9df8f..56c3d53e2109f30 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_global_client.test.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/clients/ui_settings_global_client.test.ts @@ -86,9 +86,14 @@ describe('ui settings global client', () => { const { uiSettingsClient, savedObjectsClient } = setup(); await uiSettingsClient.set('settingA', 'cde'); expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(savedObjectsClient.update).toHaveBeenCalledWith(TYPE, ID, { - settingA: 'cde', - }); + expect(savedObjectsClient.update).toHaveBeenCalledWith( + TYPE, + ID, + { + settingA: 'cde', + }, + { refresh: false } + ); }); }); diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts index 63a80e673a487c4..9f74929aaf2ccfa 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/create_or_upgrade_saved_config/create_or_upgrade_saved_config.test.ts @@ -79,6 +79,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { }, { id: version, + refresh: false, } ); }); @@ -110,6 +111,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { }, { id: version, + refresh: false, } ); }); @@ -140,7 +142,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { defaultIndex: 'another-index', isDefaultIndexMigrated: true, }, - { id: version } + { id: version, refresh: false } ); }); @@ -282,6 +284,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { }, { id: version, + refresh: false, } ); }); @@ -313,6 +316,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { }, { id: version, + refresh: false, } ); }); diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/src/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts b/packages/core/ui-settings/core-ui-settings-server-internal/src/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts index d6e0fffa05868f4..53ec0b78d3f8960 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/src/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts +++ b/packages/core/ui-settings/core-ui-settings-server-internal/src/create_or_upgrade_saved_config/create_or_upgrade_saved_config.ts @@ -63,7 +63,7 @@ export async function createOrUpgradeSavedConfig( try { // create the new SavedConfig - await savedObjectsClient.create(type, attributes, { id: version }); + await savedObjectsClient.create(type, attributes, { id: version, refresh: false }); } catch (error) { if (handleWriteErrors) { if (SavedObjectsErrorHelpers.isConflictError(error)) { diff --git a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts index 2f02b51be5501c1..2c23eec3ca2aad5 100644 --- a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts +++ b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts @@ -26,6 +26,7 @@ export async function emptyKibanaIndexAction({ await cleanSavedObjectIndices({ client, stats, log }); await migrateSavedObjectIndices(kbnClient); + await client.indices.refresh({ index: ALL_SAVED_OBJECT_INDICES }); ALL_SAVED_OBJECT_INDICES.forEach((indexPattern) => stats.createdIndex(indexPattern)); return stats.toJSON(); } diff --git a/src/core/server/integration_tests/ui_settings/doc_missing.ts b/src/core/server/integration_tests/ui_settings/doc_missing.ts index b31514d4d11c85d..4e04b0ecbd14970 100644 --- a/src/core/server/integration_tests/ui_settings/doc_missing.ts +++ b/src/core/server/integration_tests/ui_settings/doc_missing.ts @@ -13,6 +13,8 @@ export const docMissingSuite = (savedObjectsIndex: string) => () => { beforeEach(async () => { const { esClient } = getServices(); + await esClient.indices.refresh({ index: savedObjectsIndex }); + // delete all docs from kibana index to ensure savedConfig is not found await esClient.deleteByQuery({ index: savedObjectsIndex, From 7429c824bfcd2df884ee6a7c2659f59a2db63fa0 Mon Sep 17 00:00:00 2001 From: Antonio Date: Tue, 25 Jul 2023 13:27:11 +0200 Subject: [PATCH 12/29] [Cases] Total external references and persistable state attachments per case (#162071) Connected to https://github.com/elastic/kibana/issues/146945 ## Summary | Description | Limit | Done? | Documented? | ------------- | ---- | :---: | ---- | | Total number of attachments (external references and persistable state) per case | 100 | :white_check_mark: | No | ### Checklist Delete any items that are not applicable to this PR. - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### Release Notes A case can now only have 100 external references and persistable state(excluding files) attachments combined. --- .../plugins/cases/common/constants/index.ts | 1 + .../plugins/cases/server/client/cases/mock.ts | 12 +- .../common/limiter_checker/base_limiter.ts | 4 +- .../server/common/limiter_checker/index.ts | 7 +- ...able_state_and_external_references.test.ts | 85 ++++++ ...rsistable_state_and_external_references.ts | 37 +++ .../common/limiter_checker/test_utils.ts | 33 +++ .../common/models/case_with_comments.test.ts | 92 +++++++ .../plugins/cases/server/common/utils.test.ts | 28 ++ x-pack/plugins/cases/server/common/utils.ts | 10 + .../server/services/attachments/index.test.ts | 107 ++++++++ .../server/services/attachments/index.ts | 51 +++- x-pack/plugins/cases/server/services/mocks.ts | 1 + .../tests/common/comments/post_comment.ts | 72 ++++++ .../internal/bulk_create_attachments.ts | 242 ++++++++++++------ 15 files changed, 693 insertions(+), 89 deletions(-) create mode 100644 x-pack/plugins/cases/server/common/limiter_checker/limiters/persistable_state_and_external_references.test.ts create mode 100644 x-pack/plugins/cases/server/common/limiter_checker/limiters/persistable_state_and_external_references.ts diff --git a/x-pack/plugins/cases/common/constants/index.ts b/x-pack/plugins/cases/common/constants/index.ts index dcaf2bb0e646087..45125e4411f3a84 100644 --- a/x-pack/plugins/cases/common/constants/index.ts +++ b/x-pack/plugins/cases/common/constants/index.ts @@ -127,6 +127,7 @@ export const MAX_DELETE_IDS_LENGTH = 100 as const; export const MAX_SUGGESTED_PROFILES = 10 as const; export const MAX_CASES_TO_UPDATE = 100 as const; export const MAX_BULK_CREATE_ATTACHMENTS = 100 as const; +export const MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES = 100 as const; /** * Cases features diff --git a/x-pack/plugins/cases/server/client/cases/mock.ts b/x-pack/plugins/cases/server/client/cases/mock.ts index bee726524061a3f..ca96d20bad57000 100644 --- a/x-pack/plugins/cases/server/client/cases/mock.ts +++ b/x-pack/plugins/cases/server/client/cases/mock.ts @@ -9,7 +9,7 @@ import type { CaseUserActionsDeprecatedResponse } from '../../../common/types/ap import { ConnectorTypes, UserActionActions } from '../../../common/types/domain'; import type { Comment, CommentResponseAlertsType } from '../../../common/api'; import { CommentType, ExternalReferenceStorageType } from '../../../common/api'; -import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; +import { FILE_ATTACHMENT_TYPE, SECURITY_SOLUTION_OWNER } from '../../../common/constants'; export const updateUser = { updated_at: '2020-03-13T08:34:53.450Z', @@ -228,6 +228,16 @@ export const commentPersistableState: Comment = { version: 'WzEsMV0=', }; +export const commentFileExternalReference: Comment = { + ...commentExternalReference, + externalReferenceAttachmentTypeId: FILE_ATTACHMENT_TYPE, + externalReferenceMetadata: { files: [{ name: '', extension: '', mimeType: '', created: '' }] }, + externalReferenceStorage: { + type: ExternalReferenceStorageType.savedObject as const, + soType: 'file', + }, +}; + export const basicParams = { description: 'a description', title: 'a title', diff --git a/x-pack/plugins/cases/server/common/limiter_checker/base_limiter.ts b/x-pack/plugins/cases/server/common/limiter_checker/base_limiter.ts index cf9fcec712e6177..f4e72554636aecb 100644 --- a/x-pack/plugins/cases/server/common/limiter_checker/base_limiter.ts +++ b/x-pack/plugins/cases/server/common/limiter_checker/base_limiter.ts @@ -10,8 +10,8 @@ import type { Limiter } from './types'; interface LimiterParams { limit: number; - attachmentType: CommentType; - field: string; + attachmentType: CommentType | CommentType[]; + field?: string; attachmentNoun: string; } diff --git a/x-pack/plugins/cases/server/common/limiter_checker/index.ts b/x-pack/plugins/cases/server/common/limiter_checker/index.ts index 97928f2eeb35642..1ef34d70e7e257f 100644 --- a/x-pack/plugins/cases/server/common/limiter_checker/index.ts +++ b/x-pack/plugins/cases/server/common/limiter_checker/index.ts @@ -13,6 +13,7 @@ import type { AttachmentService } from '../../services'; import type { Limiter } from './types'; import { AlertLimiter } from './limiters/alerts'; import { FileLimiter } from './limiters/files'; +import { PersistableStateAndExternalReferencesLimiter } from './limiters/persistable_state_and_external_references'; export class AttachmentLimitChecker { private readonly limiters: Limiter[]; @@ -22,7 +23,11 @@ export class AttachmentLimitChecker { fileService: FileServiceStart, private readonly caseId: string ) { - this.limiters = [new AlertLimiter(attachmentService), new FileLimiter(fileService)]; + this.limiters = [ + new AlertLimiter(attachmentService), + new FileLimiter(fileService), + new PersistableStateAndExternalReferencesLimiter(attachmentService), + ]; } public async validate(requests: CommentRequest[]) { diff --git a/x-pack/plugins/cases/server/common/limiter_checker/limiters/persistable_state_and_external_references.test.ts b/x-pack/plugins/cases/server/common/limiter_checker/limiters/persistable_state_and_external_references.test.ts new file mode 100644 index 000000000000000..df40e3841f1d76d --- /dev/null +++ b/x-pack/plugins/cases/server/common/limiter_checker/limiters/persistable_state_and_external_references.test.ts @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createAttachmentServiceMock } from '../../../services/mocks'; +import { PersistableStateAndExternalReferencesLimiter } from './persistable_state_and_external_references'; +import { + createExternalReferenceRequests, + createFileRequests, + createPersistableStateRequests, + createUserRequests, +} from '../test_utils'; +import { MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES } from '../../../../common/constants'; + +describe('PersistableStateAndExternalReferencesLimiter', () => { + const caseId = 'test-id'; + const attachmentService = createAttachmentServiceMock(); + attachmentService.countPersistableStateAndExternalReferenceAttachments.mockResolvedValue(1); + + const limiter = new PersistableStateAndExternalReferencesLimiter(attachmentService); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('public fields', () => { + it('sets the errorMessage to the 100 limit', () => { + expect(limiter.errorMessage).toMatchInlineSnapshot( + `"Case has reached the maximum allowed number (100) of attached persistable state and external reference attachments."` + ); + }); + + it('sets the limit to 100', () => { + expect(limiter.limit).toBe(MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES); + }); + }); + + describe('countOfItemsWithinCase', () => { + it('calls the attachment service with the right params', () => { + limiter.countOfItemsWithinCase(caseId); + + expect( + attachmentService.countPersistableStateAndExternalReferenceAttachments + ).toHaveBeenCalledWith({ caseId }); + }); + }); + + describe('countOfItemsInRequest', () => { + it('returns 0 when passed an empty array', () => { + expect(limiter.countOfItemsInRequest([])).toBe(0); + }); + + it('returns 0 when the requests are not for persistable state attachments or external references', () => { + expect(limiter.countOfItemsInRequest(createUserRequests(2))).toBe(0); + }); + + it('counts persistable state attachments or external references correctly', () => { + expect( + limiter.countOfItemsInRequest([ + createPersistableStateRequests(1)[0], + createExternalReferenceRequests(1)[0], + createUserRequests(1)[0], + createFileRequests({ + numRequests: 1, + numFiles: 1, + })[0], + ]) + ).toBe(2); + }); + + it('excludes fileAttachmentsRequests from the count', () => { + expect( + limiter.countOfItemsInRequest( + createFileRequests({ + numRequests: 1, + numFiles: 1, + }) + ) + ).toBe(0); + }); + }); +}); diff --git a/x-pack/plugins/cases/server/common/limiter_checker/limiters/persistable_state_and_external_references.ts b/x-pack/plugins/cases/server/common/limiter_checker/limiters/persistable_state_and_external_references.ts new file mode 100644 index 000000000000000..b16baa919cffdbc --- /dev/null +++ b/x-pack/plugins/cases/server/common/limiter_checker/limiters/persistable_state_and_external_references.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AttachmentService } from '../../../services'; +import { CommentType } from '../../../../common/api'; +import type { CommentRequest } from '../../../../common/api'; +import { MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES } from '../../../../common/constants'; +import { isFileAttachmentRequest, isPersistableStateOrExternalReference } from '../../utils'; +import { BaseLimiter } from '../base_limiter'; + +export class PersistableStateAndExternalReferencesLimiter extends BaseLimiter { + constructor(private readonly attachmentService: AttachmentService) { + super({ + limit: MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES, + attachmentType: [CommentType.persistableState, CommentType.externalReference], + attachmentNoun: 'persistable state and external reference attachments', + }); + } + + public async countOfItemsWithinCase(caseId: string): Promise { + return this.attachmentService.countPersistableStateAndExternalReferenceAttachments({ + caseId, + }); + } + + public countOfItemsInRequest(requests: CommentRequest[]): number { + const totalReferences = requests + .filter(isPersistableStateOrExternalReference) + .filter((request) => !isFileAttachmentRequest(request)); + + return totalReferences.length; + } +} diff --git a/x-pack/plugins/cases/server/common/limiter_checker/test_utils.ts b/x-pack/plugins/cases/server/common/limiter_checker/test_utils.ts index f0c990e439bdf40..fc9515c133069a8 100644 --- a/x-pack/plugins/cases/server/common/limiter_checker/test_utils.ts +++ b/x-pack/plugins/cases/server/common/limiter_checker/test_utils.ts @@ -11,6 +11,8 @@ import type { CommentRequestUserType, CommentRequestAlertType, FileAttachmentMetadata, + CommentRequestPersistableStateType, + CommentRequestExternalReferenceType, } from '../../../common/api'; import type { FileAttachmentRequest } from '../types'; @@ -26,6 +28,37 @@ export const createUserRequests = (num: number): CommentRequestUserType[] => { return requests; }; +export const createPersistableStateRequests = ( + num: number +): CommentRequestPersistableStateType[] => { + return [...Array(num).keys()].map(() => { + return { + persistableStateAttachmentTypeId: '.test', + persistableStateAttachmentState: {}, + type: CommentType.persistableState as const, + owner: 'test', + }; + }); +}; + +export const createExternalReferenceRequests = ( + num: number +): CommentRequestExternalReferenceType[] => { + return [...Array(num).keys()].map((value) => { + return { + type: CommentType.externalReference as const, + owner: 'test', + externalReferenceAttachmentTypeId: '.test', + externalReferenceId: 'so-id', + externalReferenceMetadata: {}, + externalReferenceStorage: { + soType: `${value}`, + type: ExternalReferenceStorageType.savedObject, + }, + }; + }); +}; + export const createFileRequests = ({ numRequests, numFiles, diff --git a/x-pack/plugins/cases/server/common/models/case_with_comments.test.ts b/x-pack/plugins/cases/server/common/models/case_with_comments.test.ts index 94b3ac3e3be3dfd..779ed8767a9b330 100644 --- a/x-pack/plugins/cases/server/common/models/case_with_comments.test.ts +++ b/x-pack/plugins/cases/server/common/models/case_with_comments.test.ts @@ -10,6 +10,12 @@ import type { SavedObject } from '@kbn/core-saved-objects-api-server'; import { createCasesClientMockArgs } from '../../client/mocks'; import { alertComment, comment, mockCaseComments, mockCases, multipleAlert } from '../../mocks'; import { CaseCommentModel } from './case_with_comments'; +import { MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES } from '../../../common/constants'; +import { + commentExternalReference, + commentFileExternalReference, + commentPersistableState, +} from '../../client/cases/mock'; describe('CaseCommentModel', () => { const theCase = mockCases[0]; @@ -267,6 +273,52 @@ describe('CaseCommentModel', () => { expect(clientArgs.services.attachmentService.create).not.toHaveBeenCalled(); }); + + describe('validation', () => { + clientArgs.services.attachmentService.countPersistableStateAndExternalReferenceAttachments.mockResolvedValue( + MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES + ); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('throws if limit is reached when creating persistable state attachment', async () => { + await expect( + model.createComment({ + id: 'comment-1', + commentReq: commentPersistableState, + createdDate, + }) + ).rejects.toThrow( + `Case has reached the maximum allowed number (${MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES}) of attached persistable state and external reference attachments.` + ); + }); + + it('throws if limit is reached when creating external reference', async () => { + await expect( + model.createComment({ + id: 'comment-1', + commentReq: commentExternalReference, + createdDate, + }) + ).rejects.toThrow( + `Case has reached the maximum allowed number (${MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES}) of attached persistable state and external reference attachments.` + ); + }); + + it('does not throw if creating a file external reference and the limit is reached', async () => { + clientArgs.fileService.find.mockResolvedValue({ total: 0, files: [] }); + + await expect( + model.createComment({ + id: 'comment-1', + commentReq: commentFileExternalReference, + createdDate, + }) + ).resolves.not.toThrow(); + }); + }); }); describe('bulkCreate', () => { @@ -526,5 +578,45 @@ describe('CaseCommentModel', () => { expect(multipleAlertsCall.attributes.alertId).toEqual(['test-id-3', 'test-id-5']); expect(multipleAlertsCall.attributes.index).toEqual(['test-index-3', 'test-index-5']); }); + + describe('validation', () => { + clientArgs.services.attachmentService.countPersistableStateAndExternalReferenceAttachments.mockResolvedValue( + MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES + ); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('throws if limit is reached when creating persistable state attachment', async () => { + await expect( + model.bulkCreate({ + attachments: [commentPersistableState], + }) + ).rejects.toThrow( + `Case has reached the maximum allowed number (${MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES}) of attached persistable state and external reference attachments.` + ); + }); + + it('throws if limit is reached when creating external reference', async () => { + await expect( + model.bulkCreate({ + attachments: [commentExternalReference], + }) + ).rejects.toThrow( + `Case has reached the maximum allowed number (${MAX_PERSISTABLE_STATE_AND_EXTERNAL_REFERENCES}) of attached persistable state and external reference attachments.` + ); + }); + + it('does not throw if creating a file external reference and the limit is reached', async () => { + clientArgs.fileService.find.mockResolvedValue({ total: 0, files: [] }); + + await expect( + model.bulkCreate({ + attachments: [commentFileExternalReference], + }) + ).resolves.not.toThrow(); + }); + }); }); }); diff --git a/x-pack/plugins/cases/server/common/utils.test.ts b/x-pack/plugins/cases/server/common/utils.test.ts index 1c42d75be05d10d..ce470b66080ca81 100644 --- a/x-pack/plugins/cases/server/common/utils.test.ts +++ b/x-pack/plugins/cases/server/common/utils.test.ts @@ -33,6 +33,7 @@ import { getCaseViewPath, isSOError, countUserAttachments, + isPersistableStateOrExternalReference, } from './utils'; import { newCase } from '../routes/api/__mocks__/request_responses'; import { CASE_VIEW_PAGE_TABS } from '../../common/types'; @@ -40,6 +41,12 @@ import { mockCases, mockCaseComments } from '../mocks'; import { createAlertAttachment, createUserAttachment } from '../services/attachments/test_utils'; import type { CaseConnector } from '../../common/types/domain'; import { ConnectorTypes } from '../../common/types/domain'; +import { + createAlertRequests, + createExternalReferenceRequests, + createPersistableStateRequests, + createUserRequests, +} from './limiter_checker/test_utils'; interface CommentReference { ids: string[]; @@ -1353,4 +1360,25 @@ describe('common utils', () => { expect(countUserAttachments(attachments)).toBe(0); }); }); + + describe('isPersistableStateOrExternalReference', () => { + it('returns true for persistable state request', () => { + expect(isPersistableStateOrExternalReference(createPersistableStateRequests(1)[0])).toBe( + true + ); + }); + + it('returns true for external reference request', () => { + expect(isPersistableStateOrExternalReference(createExternalReferenceRequests(1)[0])).toBe( + true + ); + }); + + it('returns false for other request types', () => { + expect(isPersistableStateOrExternalReference(createUserRequests(1)[0])).toBe(false); + expect(isPersistableStateOrExternalReference(createAlertRequests(1, 'alert-id')[0])).toBe( + false + ); + }); + }); }); diff --git a/x-pack/plugins/cases/server/common/utils.ts b/x-pack/plugins/cases/server/common/utils.ts index 78a4ffeb7593ff0..64e25eb78ac7bd0 100644 --- a/x-pack/plugins/cases/server/common/utils.ts +++ b/x-pack/plugins/cases/server/common/utils.ts @@ -254,6 +254,16 @@ export const isCommentRequestTypeAlert = ( return context.type === CommentType.alert; }; +/** + * Returns true if a Comment Request is trying to create either a persistableState or an + * externalReference attachment. + */ +export const isPersistableStateOrExternalReference = (context: CommentRequest): boolean => { + return ( + context.type === CommentType.persistableState || context.type === CommentType.externalReference + ); +}; + /** * A type narrowing function for file attachments. */ diff --git a/x-pack/plugins/cases/server/services/attachments/index.test.ts b/x-pack/plugins/cases/server/services/attachments/index.test.ts index 54a48f0a53c67b4..610ce7df5bb9d21 100644 --- a/x-pack/plugins/cases/server/services/attachments/index.test.ts +++ b/x-pack/plugins/cases/server/services/attachments/index.test.ts @@ -537,4 +537,111 @@ describe('AttachmentService', () => { }); }); }); + + describe('countPersistableStateAndExternalReferenceAttachments', () => { + it('does not throw and calls unsecuredSavedObjectsClient.find with the right parameters', async () => { + unsecuredSavedObjectsClient.find.mockResolvedValue( + createSOFindResponse([{ ...createUserAttachment(), score: 0 }]) + ); + + await expect( + service.countPersistableStateAndExternalReferenceAttachments({ caseId: 'test-id' }) + ).resolves.not.toThrow(); + + expect(unsecuredSavedObjectsClient.find.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "filter": Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "cases-comments.attributes.type", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "persistableState", + }, + ], + "function": "is", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "cases-comments.attributes.type", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": "externalReference", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "or", + "type": "function", + }, + Object { + "arguments": Array [ + Object { + "arguments": Array [ + Object { + "isQuoted": false, + "type": "literal", + "value": "cases-comments.attributes.externalReferenceAttachmentTypeId", + }, + Object { + "isQuoted": false, + "type": "literal", + "value": ".files", + }, + ], + "function": "is", + "type": "function", + }, + ], + "function": "not", + "type": "function", + }, + ], + "function": "and", + "type": "function", + }, + "hasReference": Object { + "id": "test-id", + "type": "cases", + }, + "page": 1, + "perPage": 1, + "sortField": "created_at", + "type": "cases-comments", + } + `); + }); + + it('returns the expected total', async () => { + const total = 3; + + unsecuredSavedObjectsClient.find.mockResolvedValue( + createSOFindResponse( + Array(total).fill({ ...createUserAttachment({ foo: 'bar' }), score: 0 }) + ) + ); + + const res = await service.countPersistableStateAndExternalReferenceAttachments({ + caseId: 'test-id', + }); + + expect(res).toBe(total); + }); + }); }); diff --git a/x-pack/plugins/cases/server/services/attachments/index.ts b/x-pack/plugins/cases/server/services/attachments/index.ts index b0d282e00aa96c9..8f5c9ee69c07c80 100644 --- a/x-pack/plugins/cases/server/services/attachments/index.ts +++ b/x-pack/plugins/cases/server/services/attachments/index.ts @@ -14,8 +14,13 @@ import type { } from '@kbn/core/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { fromKueryExpression } from '@kbn/es-query'; import { CommentAttributesRt, CommentType, decodeOrThrow } from '../../../common/api'; -import { CASE_COMMENT_SAVED_OBJECT, CASE_SAVED_OBJECT } from '../../../common/constants'; +import { + CASE_COMMENT_SAVED_OBJECT, + CASE_SAVED_OBJECT, + FILE_ATTACHMENT_TYPE, +} from '../../../common/constants'; import { buildFilter, combineFilters } from '../../client/utils'; import { defaultSortField, isSOError } from '../../common/utils'; import type { AggregationResponse } from '../../client/metrics/types'; @@ -124,6 +129,50 @@ export class AttachmentService { } } + /** + * Counts the persistableState and externalReference attachments that are not .files + */ + public async countPersistableStateAndExternalReferenceAttachments({ + caseId, + }: { + caseId: string; + }): Promise { + try { + this.context.log.debug( + `Attempting to count persistableState and externalReference attachments for case id ${caseId}` + ); + + const typeFilter = buildFilter({ + filters: [CommentType.persistableState, CommentType.externalReference], + field: 'type', + operator: 'or', + type: CASE_COMMENT_SAVED_OBJECT, + }); + + const excludeFilesFilter = fromKueryExpression( + `not ${CASE_COMMENT_SAVED_OBJECT}.attributes.externalReferenceAttachmentTypeId: ${FILE_ATTACHMENT_TYPE}` + ); + + const combinedFilter = combineFilters([typeFilter, excludeFilesFilter]); + + const response = await this.context.unsecuredSavedObjectsClient.find<{ total: number }>({ + type: CASE_COMMENT_SAVED_OBJECT, + hasReference: { type: CASE_SAVED_OBJECT, id: caseId }, + page: 1, + perPage: 1, + sortField: defaultSortField, + filter: combinedFilter, + }); + + return response.total; + } catch (error) { + this.context.log.error( + `Error while attempting to count persistableState and externalReference attachments for case id ${caseId}: ${error}` + ); + throw error; + } + } + /** * Executes the aggregations against the actions attached to a case. */ diff --git a/x-pack/plugins/cases/server/services/mocks.ts b/x-pack/plugins/cases/server/services/mocks.ts index e9cb492e3945882..b43a3c226b1e48a 100644 --- a/x-pack/plugins/cases/server/services/mocks.ts +++ b/x-pack/plugins/cases/server/services/mocks.ts @@ -177,6 +177,7 @@ export const createAttachmentServiceMock = (): AttachmentServiceMock => { countAlertsAttachedToCase: jest.fn(), executeCaseActionsAggregations: jest.fn(), executeCaseAggregations: jest.fn(), + countPersistableStateAndExternalReferenceAttachments: jest.fn(), }; // the cast here is required because jest.Mocked tries to include private members and would throw an error diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts index 8851a95c6ebc357..0bcde310a224b91 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts @@ -16,6 +16,7 @@ import { CaseStatuses, CommentRequestExternalReferenceSOType, CommentRequestAlertType, + ExternalReferenceStorageType, } from '@kbn/cases-plugin/common/api'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { @@ -42,6 +43,7 @@ import { getCaseUserActions, removeServerGeneratedPropertiesFromUserAction, getAllComments, + bulkCreateAttachments, } from '../../../../common/lib/api'; import { createSignalsIndex, @@ -468,6 +470,76 @@ export default ({ getService }: FtrProviderContext): void => { expectedHttpCode: 400, }); }); + + it('400s when attempting to add a persistable state to a case that already has 100', async () => { + const postedCase = await createCase(supertest, postCaseReq); + + const attachments = Array(100).fill({ + type: CommentType.externalReference as const, + owner: 'securitySolutionFixture', + externalReferenceAttachmentTypeId: '.test', + externalReferenceId: 'so-id', + externalReferenceMetadata: {}, + externalReferenceStorage: { + soType: 'external-ref', + type: ExternalReferenceStorageType.savedObject as const, + }, + }); + + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: attachments, + expectedHttpCode: 200, + }); + + await createComment({ + supertest, + caseId: postedCase.id, + params: { + persistableStateAttachmentTypeId: '.test', + persistableStateAttachmentState: {}, + type: CommentType.persistableState as const, + owner: 'securitySolutionFixture', + }, + expectedHttpCode: 400, + }); + }); + + it('400s when attempting to add an external reference to a case that already has 100', async () => { + const postedCase = await createCase(supertest, postCaseReq); + + const attachments = Array(100).fill({ + persistableStateAttachmentTypeId: '.test', + persistableStateAttachmentState: {}, + type: CommentType.persistableState as const, + owner: 'securitySolutionFixture', + }); + + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: attachments, + expectedHttpCode: 200, + }); + + await createComment({ + supertest, + caseId: postedCase.id, + params: { + type: CommentType.externalReference as const, + owner: 'securitySolutionFixture', + externalReferenceAttachmentTypeId: '.test', + externalReferenceId: 'so-id', + externalReferenceMetadata: {}, + externalReferenceStorage: { + soType: 'external-ref', + type: ExternalReferenceStorageType.savedObject as const, + }, + }, + expectedHttpCode: 400, + }); + }); }); describe('alerts', () => { diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts index a0b626482f4737b..e5eaedb6dae8c5c 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts @@ -15,6 +15,7 @@ import { CaseStatuses, CommentRequestExternalReferenceSOType, CommentType, + ExternalReferenceStorageType, } from '@kbn/cases-plugin/common/api'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { @@ -42,6 +43,7 @@ import { createAndUploadFile, deleteAllFiles, getAllComments, + createComment, } from '../../../../common/lib/api'; import { createSignalsIndex, @@ -619,102 +621,174 @@ export default ({ getService }: FtrProviderContext): void => { await createCaseAndBulkCreateAttachments({ supertest, expectedHttpCode: 400 }); }); - it('400s when attempting to add more than 1K alerts to a case', async () => { - const alerts = [...Array(1001).keys()].map((num) => `test-${num}`); - const postedCase = await createCase(supertest, postCaseReq); - await bulkCreateAttachments({ - supertest, - caseId: postedCase.id, - params: [ - { - ...postCommentAlertReq, - alertId: alerts, - index: alerts, - }, - ], - expectedHttpCode: 400, + describe('validation', () => { + it('400s when attempting to add more than 1K alerts to a case', async () => { + const alerts = [...Array(1001).keys()].map((num) => `test-${num}`); + const postedCase = await createCase(supertest, postCaseReq); + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: [ + { + ...postCommentAlertReq, + alertId: alerts, + index: alerts, + }, + ], + expectedHttpCode: 400, + }); }); - }); - it('400s when attempting to add more than 1K alerts to a case in the same request', async () => { - const alerts = [...Array(1001).keys()].map((num) => `test-${num}`); - const postedCase = await createCase(supertest, postCaseReq); - await bulkCreateAttachments({ - supertest, - caseId: postedCase.id, - params: [ - { - ...postCommentAlertReq, - alertId: alerts.slice(0, 500), - index: alerts.slice(0, 500), - }, - { - ...postCommentAlertReq, - alertId: alerts.slice(500, alerts.length), - index: alerts.slice(500, alerts.length), - }, - postCommentAlertReq, - ], - expectedHttpCode: 400, + it('400s when attempting to add more than 1K alerts to a case in the same request', async () => { + const alerts = [...Array(1001).keys()].map((num) => `test-${num}`); + const postedCase = await createCase(supertest, postCaseReq); + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: [ + { + ...postCommentAlertReq, + alertId: alerts.slice(0, 500), + index: alerts.slice(0, 500), + }, + { + ...postCommentAlertReq, + alertId: alerts.slice(500, alerts.length), + index: alerts.slice(500, alerts.length), + }, + postCommentAlertReq, + ], + expectedHttpCode: 400, + }); }); - }); - it('400s when attempting to add an alert to a case that already has 1K alerts', async () => { - const alerts = [...Array(1000).keys()].map((num) => `test-${num}`); - const postedCase = await createCase(supertest, postCaseReq); - await bulkCreateAttachments({ - supertest, - caseId: postedCase.id, - params: [ - { - ...postCommentAlertReq, - alertId: alerts, - index: alerts, - }, - ], + it('400s when attempting to add an alert to a case that already has 1K alerts', async () => { + const alerts = [...Array(1000).keys()].map((num) => `test-${num}`); + const postedCase = await createCase(supertest, postCaseReq); + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: [ + { + ...postCommentAlertReq, + alertId: alerts, + index: alerts, + }, + ], + }); + + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: [ + { + ...postCommentAlertReq, + alertId: 'test-id', + index: 'test-index', + }, + ], + expectedHttpCode: 400, + }); }); - await bulkCreateAttachments({ - supertest, - caseId: postedCase.id, - params: [ - { - ...postCommentAlertReq, - alertId: 'test-id', - index: 'test-index', - }, - ], - expectedHttpCode: 400, + it('400s when the case already has alerts and the sum of existing and new alerts exceed 1k', async () => { + const alerts = [...Array(1200).keys()].map((num) => `test-${num}`); + const postedCase = await createCase(supertest, postCaseReq); + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: [ + { + ...postCommentAlertReq, + alertId: alerts.slice(0, 500), + index: alerts.slice(0, 500), + }, + ], + }); + + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: [ + { + ...postCommentAlertReq, + alertId: alerts.slice(500), + index: alerts.slice(500), + }, + postCommentAlertReq, + ], + expectedHttpCode: 400, + }); }); - }); - it('400s when the case already has alerts and the sum of existing and new alerts exceed 1k', async () => { - const alerts = [...Array(1200).keys()].map((num) => `test-${num}`); - const postedCase = await createCase(supertest, postCaseReq); - await bulkCreateAttachments({ - supertest, - caseId: postedCase.id, - params: [ - { - ...postCommentAlertReq, - alertId: alerts.slice(0, 500), - index: alerts.slice(0, 500), + it('400s when attempting to bulk create persistable state attachments reaching the 100 limit', async () => { + const postedCase = await createCase(supertest, postCaseReq); + + await createComment({ + supertest, + caseId: postedCase.id, + params: { + type: CommentType.externalReference as const, + owner: 'securitySolutionFixture', + externalReferenceAttachmentTypeId: '.test', + externalReferenceId: 'so-id', + externalReferenceMetadata: {}, + externalReferenceStorage: { + soType: 'external-ref', + type: ExternalReferenceStorageType.savedObject as const, + }, }, - ], + expectedHttpCode: 200, + }); + + const persistableStateAttachments = Array(100).fill({ + persistableStateAttachmentTypeId: '.test', + persistableStateAttachmentState: {}, + type: CommentType.persistableState as const, + owner: 'securitySolutionFixture', + }); + + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: persistableStateAttachments, + expectedHttpCode: 400, + }); }); - await bulkCreateAttachments({ - supertest, - caseId: postedCase.id, - params: [ - { - ...postCommentAlertReq, - alertId: alerts.slice(500), - index: alerts.slice(500), + it('400s when attempting to bulk create >100 external reference attachments reaching the 100 limit', async () => { + const postedCase = await createCase(supertest, postCaseReq); + + await createComment({ + supertest, + caseId: postedCase.id, + params: { + persistableStateAttachmentTypeId: '.test', + persistableStateAttachmentState: {}, + type: CommentType.persistableState as const, + owner: 'securitySolutionFixture', }, - postCommentAlertReq, - ], - expectedHttpCode: 400, + expectedHttpCode: 200, + }); + + const externalRequestAttachments = Array(100).fill({ + type: CommentType.externalReference as const, + owner: 'securitySolutionFixture', + externalReferenceAttachmentTypeId: '.test', + externalReferenceId: 'so-id', + externalReferenceMetadata: {}, + externalReferenceStorage: { + soType: 'external-ref', + type: ExternalReferenceStorageType.savedObject as const, + }, + }); + + await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: externalRequestAttachments, + expectedHttpCode: 400, + }); }); }); }); From 89ad530e8c61b25d6c3b04705d3da6534aa6e2b3 Mon Sep 17 00:00:00 2001 From: Alexi Doak <109488926+doakalexi@users.noreply.github.com> Date: Tue, 25 Jul 2023 08:51:46 -0400 Subject: [PATCH 13/29] [ResponseOps][Alerting] ES query rule DSL editor doesn't update when you copy/paste a query (#162330) Resolves https://github.com/elastic/kibana/issues/161595 ## Summary Captures changes in the editor when copying/pasting in values. ### To verify - Create a new Es Query rule using DSL - Paste runtime mappings in your query and don't type anything else in the editor - Verify that the runtime fields are listed in the group by or aggregate over options below the query --- .../rule_types/es_query/expression/es_query_expression.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx index f3a0c0175b30044..2119879c26b3995 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx @@ -114,10 +114,10 @@ export const EsQueryExpression: React.FC< setCombinedFields(sortBy(currentEsFields.concat(runtimeFields), 'name')); }; - const getRuntimeFields = () => { + const getRuntimeFields = (xjson: string) => { let runtimeMappings; try { - runtimeMappings = get(JSON.parse(xJson), 'runtime_mappings'); + runtimeMappings = get(JSON.parse(xjson), 'runtime_mappings'); } catch (e) { // ignore error } @@ -270,7 +270,7 @@ export const EsQueryExpression: React.FC< onChange={(xjson: string) => { setXJson(xjson); setParam('esQuery', convertToJson(xjson)); - getRuntimeFields(); + getRuntimeFields(xjson); }} options={{ ariaLabel: i18n.translate('xpack.stackAlerts.esQuery.ui.queryEditor', { From 1ea9d406c18fb77465e515cc874d51c3f42317f7 Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Tue, 25 Jul 2023 08:49:55 -0500 Subject: [PATCH 14/29] [Enterprise Search] Overview Page updates (#162252) ## Summary - Added Search Applications & Behavioral Analytics product cards - Removed Search Experiences from page side nav - Hid ESRE & Search Experiences from global Kibana nav - moved Vector Search above ESRE in page nav - Re-ordered Kibana nav items per product & design requests. ### Screenshots ![image](https://github.com/elastic/kibana/assets/1972968/939fc120-afa4-4dd6-9372-2a51f5d16d21) ![image](https://github.com/elastic/kibana/assets/1972968/9102f7ad-caec-4456-8a56-e4dc4128223e) --- .../add_analytics_collection.tsx | 8 +- .../assets/behavioral_analytics_logo.svg | 17 ++ .../assets/search_applications_logo.svg | 5 + .../components/product_card/product_card.tsx | 78 +++--- .../behavioral_analytics_product_card.tsx | 55 ++++ .../elasticsearch_product_card.tsx | 97 +++++++ .../product_selector.test.tsx | 72 ++--- .../product_selector/product_selector.tsx | 253 +----------------- .../search_applications_product_card.tsx | 58 ++++ .../enterprise_search_overview/index.tsx | 6 +- .../esre/components/esre_guide/esre_guide.tsx | 2 +- .../applications/shared/layout/nav.test.tsx | 33 +-- .../public/applications/shared/layout/nav.tsx | 19 +- .../vector_search_guide.tsx | 6 +- .../enterprise_search/public/plugin.ts | 70 ++--- .../server/utils/search_result_provider.ts | 9 + .../translations/translations/fr-FR.json | 19 -- .../translations/translations/ja-JP.json | 19 -- .../translations/translations/zh-CN.json | 19 -- .../accessibility/apps/enterprise_search.ts | 61 ++++- 20 files changed, 438 insertions(+), 468 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/behavioral_analytics_logo.svg create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/search_applications_logo.svg create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/behavioral_analytics_product_card.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/elasticsearch_product_card.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/search_applications_product_card.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection.tsx index 82d27cf4a177b22..18c0207a4926b67 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection.tsx @@ -30,7 +30,13 @@ export const AddAnalyticsCollection: React.FC = ({ {render ? ( render(showModal) ) : ( - + {i18n.translate('xpack.enterpriseSearch.analytics.collections.create.buttonTitle', { defaultMessage: 'Create collection', })} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/behavioral_analytics_logo.svg b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/behavioral_analytics_logo.svg new file mode 100644 index 000000000000000..7cb264819b12fe0 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/behavioral_analytics_logo.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/search_applications_logo.svg b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/search_applications_logo.svg new file mode 100644 index 000000000000000..8854041400c719f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/assets/search_applications_logo.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.tsx index 2ad79771a43b181..959992ca4b270d3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_card/product_card.tsx @@ -22,6 +22,7 @@ import { EuiText, EuiTitle, IconType, + IconSize, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -37,15 +38,18 @@ interface ProductResourceLink { } export interface ProductCardProps { - cta: string; + cta?: string; description: string; emptyCta?: boolean; features: string[]; + hasBorder?: boolean; + hasShadow?: boolean; icon: IconType; + iconSize?: IconSize; name: string; productId: string; resourceLinks: ProductResourceLink[]; - url: string; + url?: string; } export const ProductCard: React.FC = ({ @@ -53,7 +57,10 @@ export const ProductCard: React.FC = ({ description, emptyCta = false, features, + hasBorder, + hasShadow, icon, + iconSize, productId, name, resourceLinks, @@ -63,14 +70,15 @@ export const ProductCard: React.FC = ({ return ( - + @@ -81,36 +89,38 @@ export const ProductCard: React.FC = ({ {description} -

- {emptyCta ? ( - - sendEnterpriseSearchTelemetry({ - action: 'clicked', - metric: snakeCase(productId), - }) - } - > - {cta} - - ) : ( - - sendEnterpriseSearchTelemetry({ - action: 'clicked', - metric: snakeCase(productId), - }) - } - > - {cta} - - )} -
+ {cta && url && ( +
+ {emptyCta ? ( + + sendEnterpriseSearchTelemetry({ + action: 'clicked', + metric: snakeCase(productId), + }) + } + > + {cta} + + ) : ( + + sendEnterpriseSearchTelemetry({ + action: 'clicked', + metric: snakeCase(productId), + }) + } + > + {cta} + + )} +
+ )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/behavioral_analytics_product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/behavioral_analytics_product_card.tsx new file mode 100644 index 000000000000000..52d5f1ab3d5d672 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/behavioral_analytics_product_card.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { ANALYTICS_PLUGIN } from '../../../../../common/constants'; +import { docLinks } from '../../../shared/doc_links'; +import baLogo from '../../assets/behavioral_analytics_logo.svg'; +import { ProductCard } from '../product_card'; + +export const BehavioralAnalyticsProductCard = () => ( + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/elasticsearch_product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/elasticsearch_product_card.tsx new file mode 100644 index 000000000000000..70d5f2765b4cc23 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/elasticsearch_product_card.tsx @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues } from 'kea'; + +import { i18n } from '@kbn/i18n'; + +import { ELASTICSEARCH_PLUGIN, SEARCH_EXPERIENCES_PLUGIN } from '../../../../../common/constants'; +import { docLinks } from '../../../shared/doc_links'; +import { HttpLogic } from '../../../shared/http'; +import { ProductCard } from '../product_card'; + +export const ElasticsearchProductCard = () => { + const { http } = useValues(HttpLogic); + return ( + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx index 1e4ec5ef456a0c6..a1b2b80618c3ff0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/product_selector.test.tsx @@ -11,49 +11,39 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; import { AddContentEmptyPrompt } from '../../../shared/add_content_empty_prompt'; import { ErrorStateCallout } from '../../../shared/error_state'; -import { ProductCard } from '../product_card'; import { SetupGuideCta } from '../setup_guide'; import { TrialCallout } from '../trial_callout'; -import { ProductSelector } from '.'; +import { BehavioralAnalyticsProductCard } from './behavioral_analytics_product_card'; +import { ElasticsearchProductCard } from './elasticsearch_product_card'; +import { SearchApplicationsProductCard } from './search_applications_product_card'; -const props = { - access: {}, - isWorkplaceSearchAdmin: true, -}; +import { ProductSelector } from '.'; describe('ProductSelector', () => { it('renders the overview page, product cards, & setup guide CTAs with no host set', () => { setMockValues({ config: { canDeployEntSearch: true, host: '' } }); - const wrapper = shallow(); + const wrapper = shallow(); - expect(wrapper.find(ProductCard)).toHaveLength(3); + expect(wrapper.find(ElasticsearchProductCard)).toHaveLength(1); + expect(wrapper.find(SearchApplicationsProductCard)).toHaveLength(1); + expect(wrapper.find(BehavioralAnalyticsProductCard)).toHaveLength(1); expect(wrapper.find(SetupGuideCta)).toHaveLength(1); }); it('renders the trial callout', () => { setMockValues({ config: { canDeployEntSearch: true, host: 'localhost' } }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(TrialCallout)).toHaveLength(1); }); - it('passes correct URL when Workplace Search user is not an admin', () => { - setMockValues({ config: { canDeployEntSearch: true, host: '' } }); - const wrapper = shallow(); - - expect(wrapper.find(ProductCard).last().prop('url')).toEqual( - WORKPLACE_SEARCH_PLUGIN.NON_ADMIN_URL - ); - }); - it('does not render connection error callout without an error', () => { setMockValues({ config: { canDeployEntSearch: true, host: 'localhost' } }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(ErrorStateCallout)).toHaveLength(0); }); @@ -63,14 +53,14 @@ describe('ProductSelector', () => { config: { canDeployEntSearch: true, host: 'localhost' }, errorConnectingMessage: '502 Bad Gateway', }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(ErrorStateCallout)).toHaveLength(1); }); it('renders add content', () => { setMockValues({ config: { canDeployEntSearch: true, host: 'localhost' } }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(AddContentEmptyPrompt)).toHaveLength(1); }); @@ -80,7 +70,7 @@ describe('ProductSelector', () => { config: { canDeployEntSearch: true, host: 'localhost' }, errorConnectingMessage: '502 Bad Gateway', }); - const wrapper = shallow(); + const wrapper = shallow(); expect(wrapper.find(AddContentEmptyPrompt)).toHaveLength(0); }); @@ -90,37 +80,13 @@ describe('ProductSelector', () => { setMockValues({ config: { canDeployEntSearch: true, host: 'localhost' } }); }); - it('does not render the App Search card if the user does not have access to AS', () => { - const wrapper = shallow( - - ); - - expect(wrapper.find(ProductCard)).toHaveLength(2); - expect(wrapper.find('[data-test-subj="productCard-workplaceSearch"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="productCard-elasticsearch"]')).toHaveLength(1); - }); - - it('does not render the Workplace Search card if the user does not have access to WS', () => { - const wrapper = shallow( - - ); - - expect(wrapper.find(ProductCard)).toHaveLength(2); - expect(wrapper.find('[data-test-subj="productCard-appSearch"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="productCard-elasticsearch"]')).toHaveLength(1); - }); - - it('renders elasticsearch card if the user does not have access app search & workplace search', () => { - const wrapper = shallow(); + it('does not render the Setup CTA when there is a host', () => { + const wrapper = shallow(); - expect(wrapper.find(ProductCard)).toHaveLength(1); - expect(wrapper.find('[data-test-subj="productCard-elasticsearch"]')).toHaveLength(1); + expect(wrapper.find(ElasticsearchProductCard)).toHaveLength(1); + expect(wrapper.find(SearchApplicationsProductCard)).toHaveLength(1); + expect(wrapper.find(BehavioralAnalyticsProductCard)).toHaveLength(1); + expect(wrapper.find(SetupGuideCta)).toHaveLength(0); }); }); }); 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 bda23bbc0ac3575..400d5f572ae4d51 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 @@ -13,13 +13,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; import { Chat } from '@kbn/cloud-chat-plugin/public'; import { i18n } from '@kbn/i18n'; -import { - APP_SEARCH_PLUGIN, - ELASTICSEARCH_PLUGIN, - WORKPLACE_SEARCH_PLUGIN, -} from '../../../../../common/constants'; import { AddContentEmptyPrompt } from '../../../shared/add_content_empty_prompt'; -import { docLinks } from '../../../shared/doc_links'; import { ErrorStateCallout } from '../../../shared/error_state'; import { HttpLogic } from '../../../shared/http'; import { KibanaLogic } from '../../../shared/kibana'; @@ -27,23 +21,14 @@ import { SetSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome' import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; import { EnterpriseSearchOverviewPageTemplate } from '../layout'; -import { ProductCard } from '../product_card'; import { SetupGuideCta } from '../setup_guide'; import { TrialCallout } from '../trial_callout'; -interface ProductSelectorProps { - access: { - hasAppSearchAccess?: boolean; - hasWorkplaceSearchAccess?: boolean; - }; - isWorkplaceSearchAdmin: boolean; -} +import { BehavioralAnalyticsProductCard } from './behavioral_analytics_product_card'; +import { ElasticsearchProductCard } from './elasticsearch_product_card'; +import { SearchApplicationsProductCard } from './search_applications_product_card'; -export const ProductSelector: React.FC = ({ - access, - isWorkplaceSearchAdmin, -}) => { - const { hasAppSearchAccess, hasWorkplaceSearchAccess } = access; +export const ProductSelector: React.FC = () => { const { config } = useValues(KibanaLogic); const { errorConnectingMessage } = useValues(HttpLogic); @@ -52,15 +37,6 @@ export const ProductSelector: React.FC = ({ // to no longer rely on ent-search we can always show the Add Content component const showAddContent = config.host && !errorConnectingMessage; - // If Enterprise Search hasn't been set up yet, show all products. Otherwise, only show products the user has access to - const shouldShowAppSearchCard = (!config.host && config.canDeployEntSearch) || hasAppSearchAccess; - const shouldShowWorkplaceSearchCard = - (!config.host && config.canDeployEntSearch) || hasWorkplaceSearchAccess; - - const WORKPLACE_SEARCH_URL = isWorkplaceSearchAdmin - ? WORKPLACE_SEARCH_PLUGIN.URL - : WORKPLACE_SEARCH_PLUGIN.NON_ADMIN_URL; - return ( = ({ defaultMessage: 'Create an Elasticsearch index', })} /> - + )} {showErrorConnecting && ( @@ -92,225 +68,24 @@ export const ProductSelector: React.FC = ({ )} -

{i18n.translate('xpack.enterpriseSearch.overview.productSelector.title', { - defaultMessage: 'Search experiences for every use case', + defaultMessage: "What's next?", })}

- + - + + + + + + + - {shouldShowAppSearchCard && ( - - - - )} - {shouldShowWorkplaceSearchCard && ( - - - - )} {!config.host && config.canDeployEntSearch && ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/search_applications_product_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/search_applications_product_card.tsx new file mode 100644 index 000000000000000..9283ae844d765b1 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/components/product_selector/search_applications_product_card.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; 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 { APPLICATIONS_PLUGIN } from '../../../../../common/constants'; +import { docLinks } from '../../../shared/doc_links'; +import searchAppLogo from '../../assets/search_applications_logo.svg'; +import { ProductCard } from '../product_card'; + +export const SearchApplicationsProductCard = () => ( + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.tsx index 5b8e595d6e88ed1..438b903bd839958 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/index.tsx @@ -21,8 +21,6 @@ import { SetupGuide } from './components/setup_guide'; import { ROOT_PATH, SETUP_GUIDE_PATH } from './routes'; export const EnterpriseSearchOverview: React.FC = ({ - access = {}, - workplaceSearch, enterpriseSearchVersion, kibanaVersion, }) => { @@ -31,8 +29,6 @@ export const EnterpriseSearchOverview: React.FC = ({ const incompatibleVersions = !!( config.host && isVersionMismatch(enterpriseSearchVersion, kibanaVersion) ); - const isWorkplaceSearchAdmin = !!workplaceSearch?.account?.isAdmin; - const showView = () => { if (incompatibleVersions) { return ( @@ -43,7 +39,7 @@ export const EnterpriseSearchOverview: React.FC = ({ ); } - return ; + return ; }; return ( diff --git a/x-pack/plugins/enterprise_search/public/applications/esre/components/esre_guide/esre_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/esre/components/esre_guide/esre_guide.tsx index b06759071301a61..9c320574a19d3c2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/esre/components/esre_guide/esre_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/esre/components/esre_guide/esre_guide.tsx @@ -64,7 +64,7 @@ export const EsreGuide: React.FC = () => { -

+

{ id: 'elasticsearch', name: 'Elasticsearch', }, - { - href: '/app/enterprise_search/esre', - id: 'esre', - name: 'ESRE', - }, { href: '/app/enterprise_search/vector_search', id: 'vectorSearch', name: 'Vector Search', }, { - href: '/app/enterprise_search/search_experiences', - id: 'searchExperiences', - name: 'Search Experiences', + href: '/app/enterprise_search/esre', + id: 'esre', + name: 'ESRE', }, ], name: 'Overview', @@ -220,20 +215,15 @@ describe('useEnterpriseSearchApplicationNav', () => { id: 'elasticsearch', name: 'Elasticsearch', }, - { - href: '/app/enterprise_search/esre', - id: 'esre', - name: 'ESRE', - }, { href: '/app/enterprise_search/vector_search', id: 'vectorSearch', name: 'Vector Search', }, { - href: '/app/enterprise_search/search_experiences', - id: 'searchExperiences', - name: 'Search Experiences', + href: '/app/enterprise_search/esre', + id: 'esre', + name: 'ESRE', }, ], name: 'Overview', @@ -417,20 +407,15 @@ describe('useEnterpriseSearchAnalyticsNav', () => { id: 'elasticsearch', name: 'Elasticsearch', }, - { - href: '/app/enterprise_search/esre', - id: 'esre', - name: 'ESRE', - }, { href: '/app/enterprise_search/vector_search', id: 'vectorSearch', name: 'Vector Search', }, { - href: '/app/enterprise_search/search_experiences', - id: 'searchExperiences', - name: 'Search Experiences', + href: '/app/enterprise_search/esre', + id: 'esre', + name: 'ESRE', }, ], name: 'Overview', 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 index 5579d17d018dbaa..01510fd4654b7fc 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx @@ -20,7 +20,6 @@ import { ENTERPRISE_SEARCH_CONTENT_PLUGIN, ENTERPRISE_SEARCH_OVERVIEW_PLUGIN, ESRE_PLUGIN, - SEARCH_EXPERIENCES_PLUGIN, VECTOR_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN, } from '../../../../common/constants'; @@ -55,16 +54,6 @@ export const useEnterpriseSearchNav = () => { to: ELASTICSEARCH_PLUGIN.URL, }), }, - { - id: 'esre', - name: i18n.translate('xpack.enterpriseSearch.nav.esreTitle', { - defaultMessage: 'ESRE', - }), - ...generateNavLink({ - shouldNotCreateHref: true, - to: ESRE_PLUGIN.URL, - }), - }, { id: 'vectorSearch', name: VECTOR_SEARCH_PLUGIN.NAME, @@ -74,13 +63,13 @@ export const useEnterpriseSearchNav = () => { }), }, { - id: 'searchExperiences', - name: i18n.translate('xpack.enterpriseSearch.nav.searchExperiencesTitle', { - defaultMessage: 'Search Experiences', + id: 'esre', + name: i18n.translate('xpack.enterpriseSearch.nav.esreTitle', { + defaultMessage: 'ESRE', }), ...generateNavLink({ shouldNotCreateHref: true, - to: SEARCH_EXPERIENCES_PLUGIN.URL, + to: ESRE_PLUGIN.URL, }), }, ], diff --git a/x-pack/plugins/enterprise_search/public/applications/vector_search/components/vector_search_guide/vector_search_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/vector_search/components/vector_search_guide/vector_search_guide.tsx index 1c14178b1583bf5..a7b87ae67cda741 100644 --- a/x-pack/plugins/enterprise_search/public/applications/vector_search/components/vector_search_guide/vector_search_guide.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/vector_search/components/vector_search_guide/vector_search_guide.tsx @@ -89,7 +89,11 @@ export const VectorSearchGuide: React.FC = () => { id="xpack.enterpriseSearch.vectorSearch.guide.description" defaultMessage="Elasticsearch can be used as a vector database, which enables vector search and semantic search use cases." />{' '} - + { const kibanaDeps = await this.getKibanaDeps(core, params, cloud); const { chrome, http } = kibanaDeps.core; - chrome.docTitle.change(ESRE_PLUGIN.NAME); + chrome.docTitle.change(ELASTICSEARCH_PLUGIN.NAME); await this.getInitialData(http); const pluginData = this.getPluginData(); const { renderApp } = await import('./applications'); - const { EnterpriseSearchEsre } = await import('./applications/esre'); + const { Elasticsearch } = await import('./applications/elasticsearch'); - return renderApp(EnterpriseSearchEsre, kibanaDeps, pluginData); + return renderApp(Elasticsearch, kibanaDeps, pluginData); }, - title: ESRE_PLUGIN.NAV_TITLE, + title: ELASTICSEARCH_PLUGIN.NAME, }); core.application.register({ @@ -209,6 +209,28 @@ export class EnterpriseSearchPlugin implements Plugin { title: VECTOR_SEARCH_PLUGIN.NAV_TITLE, }); + core.application.register({ + appRoute: ESRE_PLUGIN.URL, + category: DEFAULT_APP_CATEGORIES.enterpriseSearch, + euiIconType: ESRE_PLUGIN.LOGO, + id: ESRE_PLUGIN.ID, + mount: async (params: AppMountParameters) => { + const kibanaDeps = await this.getKibanaDeps(core, params, cloud); + const { chrome, http } = kibanaDeps.core; + chrome.docTitle.change(ESRE_PLUGIN.NAME); + + await this.getInitialData(http); + const pluginData = this.getPluginData(); + + const { renderApp } = await import('./applications'); + const { EnterpriseSearchEsre } = await import('./applications/esre'); + + return renderApp(EnterpriseSearchEsre, kibanaDeps, pluginData); + }, + navLinkStatus: AppNavLinkStatus.hidden, + title: ESRE_PLUGIN.NAV_TITLE, + }); + core.application.register({ appRoute: APPLICATIONS_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, @@ -256,24 +278,25 @@ export class EnterpriseSearchPlugin implements Plugin { }); core.application.register({ - appRoute: ELASTICSEARCH_PLUGIN.URL, + appRoute: SEARCH_EXPERIENCES_PLUGIN.URL, category: DEFAULT_APP_CATEGORIES.enterpriseSearch, euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO, - id: ELASTICSEARCH_PLUGIN.ID, + id: SEARCH_EXPERIENCES_PLUGIN.ID, mount: async (params: AppMountParameters) => { const kibanaDeps = await this.getKibanaDeps(core, params, cloud); const { chrome, http } = kibanaDeps.core; - chrome.docTitle.change(ELASTICSEARCH_PLUGIN.NAME); + chrome.docTitle.change(SEARCH_EXPERIENCES_PLUGIN.NAME); await this.getInitialData(http); const pluginData = this.getPluginData(); const { renderApp } = await import('./applications'); - const { Elasticsearch } = await import('./applications/elasticsearch'); + const { SearchExperiences } = await import('./applications/search_experiences'); - return renderApp(Elasticsearch, kibanaDeps, pluginData); + return renderApp(SearchExperiences, kibanaDeps, pluginData); }, - title: ELASTICSEARCH_PLUGIN.NAME, + navLinkStatus: AppNavLinkStatus.hidden, + title: SEARCH_EXPERIENCES_PLUGIN.NAME, }); if (config.canDeployEntSearch) { @@ -325,27 +348,6 @@ export class EnterpriseSearchPlugin implements Plugin { }); } - core.application.register({ - appRoute: SEARCH_EXPERIENCES_PLUGIN.URL, - category: DEFAULT_APP_CATEGORIES.enterpriseSearch, - euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO, - id: SEARCH_EXPERIENCES_PLUGIN.ID, - mount: async (params: AppMountParameters) => { - const kibanaDeps = await this.getKibanaDeps(core, params, cloud); - const { chrome, http } = kibanaDeps.core; - chrome.docTitle.change(SEARCH_EXPERIENCES_PLUGIN.NAME); - - await this.getInitialData(http); - const pluginData = this.getPluginData(); - - const { renderApp } = await import('./applications'); - const { SearchExperiences } = await import('./applications/search_experiences'); - - return renderApp(SearchExperiences, kibanaDeps, pluginData); - }, - title: SEARCH_EXPERIENCES_PLUGIN.NAME, - }); - if (plugins.home) { plugins.home.featureCatalogue.registerSolution({ description: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.DESCRIPTION, diff --git a/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts b/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts index 10168eb095801c5..13ead48887acb5e 100644 --- a/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts +++ b/x-pack/plugins/enterprise_search/server/utils/search_result_provider.ts @@ -21,6 +21,7 @@ import { ENTERPRISE_SEARCH_CONTENT_PLUGIN, APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN, + ESRE_PLUGIN, } from '../../common/constants'; type ServiceDefinition = @@ -114,6 +115,14 @@ export function getSearchResultProvider( serviceType: 'workplace_search', url: WORKPLACE_SEARCH_PLUGIN.URL, }, + { + keywords: ['esre', 'search'], + name: i18n.translate('xpack.enterpriseSearch.searchProvider.esre.name', { + defaultMessage: 'ESRE', + }), + serviceType: 'esre', + url: ESRE_PLUGIN.URL, + }, ], ]; const result = services diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 8656553f95b0f74..d631878cad2e139 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -13191,9 +13191,6 @@ "xpack.enterpriseSearch.appSearch.enginesOverview.table.column.lastUpdated": "Dernière mise à jour", "xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name": "Nom", "xpack.enterpriseSearch.appSearch.enginesOverview.title": "Aperçu des moteurs", - "xpack.enterpriseSearch.appSearch.features.ingest": "Ingestion avec un robot d'indexation, une API ou Elasticsearch", - "xpack.enterpriseSearch.appSearch.features.managementDashboards": "Tableaux de bord de gestion de recherche", - "xpack.enterpriseSearch.appSearch.features.searchApis": "API optimisées pour la recherche", "xpack.enterpriseSearch.appSearch.integrations.jsonDescription": "Recherchez dans vos données JSON avec App Search.", "xpack.enterpriseSearch.appSearch.integrations.jsonName": "JSON", "xpack.enterpriseSearch.appSearch.logRetention.callout.description.manageSettingsLinkText": "accédez à vos paramètres", @@ -13222,14 +13219,8 @@ "xpack.enterpriseSearch.appSearch.multiInputRows.inputRowPlaceholder": "Entrer une valeur", "xpack.enterpriseSearch.appSearch.multiInputRows.removeValueButtonLabel": "Retirer une valeur", "xpack.enterpriseSearch.appSearch.ownerRoleTypeDescription": "Les propriétaires peuvent tout faire. Le compte peut avoir plusieurs propriétaires, mais il doit toujours y avoir au moins un propriétaire.", - "xpack.enterpriseSearch.appSearch.productCardCTA": "Ouvrir App Search", - "xpack.enterpriseSearch.appSearch.productCardDescription": "Idéal pour les apps et les sites web, App Search vous aide à concevoir, déployer et gérer des expériences de recherche puissantes.", "xpack.enterpriseSearch.appSearch.productDescription": "Tirez parti des tableaux de bord, des analyses et des API pour simplifier la recherche d'applications avancée.", "xpack.enterpriseSearch.appSearch.productName": "App Search", - "xpack.enterpriseSearch.appSearch.resources.adaptiveRelevanceLabel": "Automatiser avec la pertinence adaptative", - "xpack.enterpriseSearch.appSearch.resources.gettingStartedLabel": "Prise en main d’App Search", - "xpack.enterpriseSearch.appSearch.resources.searchRelevanceLabel": "Ajuster votre pertinence de recherche", - "xpack.enterpriseSearch.appSearch.resources.searchUILabel": "Rechercher App Search dans l’interface utilisateur", "xpack.enterpriseSearch.appSearch.result.documentDetailLink": "Accéder aux détails des documents", "xpack.enterpriseSearch.appSearch.result.hideAdditionalFields": "Masquer les champs supplémentaires", "xpack.enterpriseSearch.appSearch.roleMappingCreatedMessage": "Votre mapping de rôles a été créé", @@ -14208,7 +14199,6 @@ "xpack.enterpriseSearch.elasticsearch.features.buildSearchExperiences": "Créer des expériences de recherche personnalisées", "xpack.enterpriseSearch.elasticsearch.features.buildTooling": "Créer des outils personnalisés", "xpack.enterpriseSearch.elasticsearch.features.integrate": "Intégrer à des bases de données, des sites web, etc.", - "xpack.enterpriseSearch.elasticsearch.productCardCTA": "Afficher le guide de configuration", "xpack.enterpriseSearch.elasticsearch.productCardDescription": "Idéal pour les applications sur mesure, Elasticsearch vous aide à créer des recherches hautement personnalisables et offre de nombreuses méthodes d'ingestion différentes.", "xpack.enterpriseSearch.elasticsearch.productDescription": "Outils de bas niveau pour la création d'expériences performantes et pertinentes.", "xpack.enterpriseSearch.elasticsearch.productName": "Elasticsearch", @@ -14411,7 +14401,6 @@ "xpack.enterpriseSearch.nav.enterpriseSearchOverviewTitle": "Aperçu", "xpack.enterpriseSearch.nav.esreTitle": "ESRE", "xpack.enterpriseSearch.nav.searchApplicationsTitle": "Applications de recherche", - "xpack.enterpriseSearch.nav.searchExperiencesTitle": "Expériences de recherche", "xpack.enterpriseSearch.nav.searchIndicesTitle": "Index", "xpack.enterpriseSearch.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.notFound.action1": "Retour à votre tableau de bord", @@ -14867,9 +14856,6 @@ "xpack.enterpriseSearch.workplaceSearch.explorePlatinumFeatures.link": "Explorer les fonctionnalités Platinum", "xpack.enterpriseSearch.workplaceSearch.externalConnectorApiKey.label": "Clé d'API du connecteur", "xpack.enterpriseSearch.workplaceSearch.externalConnectorUrl.label": "URL du connecteur", - "xpack.enterpriseSearch.workplaceSearch.features.ingest": "Ingérer à partir de sources tierces", - "xpack.enterpriseSearch.workplaceSearch.features.managementDashboards": "Tableaux de bord de gestion de recherche", - "xpack.enterpriseSearch.workplaceSearch.features.searchExperiences": "Des expériences de recherche pou les utilisateurs authentifiés", "xpack.enterpriseSearch.workplaceSearch.field.label": "Champ", "xpack.enterpriseSearch.workplaceSearch.groups.addGroup.heading": "Ajouter un groupe", "xpack.enterpriseSearch.workplaceSearch.groups.addGroup.label": "Nom du groupe", @@ -15016,8 +15002,6 @@ "xpack.enterpriseSearch.workplaceSearch.privatePlatinumCallout.text": "Les sources privées requièrent une licence Platinum.", "xpack.enterpriseSearch.workplaceSearch.privateSource.text": "Source privée", "xpack.enterpriseSearch.workplaceSearch.privateSources.text": "Sources privées", - "xpack.enterpriseSearch.workplaceSearch.productCardCTA": "Ouvrir Workplace Search", - "xpack.enterpriseSearch.workplaceSearch.productCardDescription": "Idéal pour les équipes internes, Workplace Search vous aide à unifier votre contenu dans un seul endroit, avec une connectivité instantanée à des outils populaires de productivité.", "xpack.enterpriseSearch.workplaceSearch.productCta": "Ouvrir Workplace Search", "xpack.enterpriseSearch.workplaceSearch.productDescription": "Effectuez des recherches dans tous les documents, fichiers et sources disponibles sur votre lieu de travail virtuel.", "xpack.enterpriseSearch.workplaceSearch.productName": "Workplace Search", @@ -15032,9 +15016,6 @@ "xpack.enterpriseSearch.workplaceSearch.remove.button": "Retirer", "xpack.enterpriseSearch.workplaceSearch.removeField.label": "Retirer le champ", "xpack.enterpriseSearch.workplaceSearch.reset.button": "Réinitialiser", - "xpack.enterpriseSearch.workplaceSearch.resources.gettingStartedLabel": "Prise en main de Workplace Search", - "xpack.enterpriseSearch.workplaceSearch.resources.managePermissionsLabel": "Gérer les autorisations", - "xpack.enterpriseSearch.workplaceSearch.resources.setUpConnectorsLabel": "Configurer vos connecteurs", "xpack.enterpriseSearch.workplaceSearch.roleMapping.adminRoleTypeDescription": "Les administrateurs disposent d'un accès total à tous les paramètres concernant toute l'organisation, y compris la fonctionnalité de gestion des utilisateurs, des groupes et des sources de contenu.", "xpack.enterpriseSearch.workplaceSearch.roleMapping.allGroupsDescription": "L'attribution à tous les groupes comprend tous les groupes actuels et futurs tels qu'ils ont été créés ou seront créés et administrés à une date ultérieure.", "xpack.enterpriseSearch.workplaceSearch.roleMapping.allGroupsLabel": "Attribuer à tous les groupes", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 41a4a389bd60a55..6a00f5bf7037a12 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -13205,9 +13205,6 @@ "xpack.enterpriseSearch.appSearch.enginesOverview.table.column.lastUpdated": "最終更新", "xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name": "名前", "xpack.enterpriseSearch.appSearch.enginesOverview.title": "エンジン概要", - "xpack.enterpriseSearch.appSearch.features.ingest": "Webクローラー、API、Elasticsearchで取り込む", - "xpack.enterpriseSearch.appSearch.features.managementDashboards": "検索管理ダッシュボード", - "xpack.enterpriseSearch.appSearch.features.searchApis": "検索に合わせて最適化されたAPI", "xpack.enterpriseSearch.appSearch.integrations.jsonDescription": "App Searchを使用して、JSONデータを検索します。", "xpack.enterpriseSearch.appSearch.integrations.jsonName": "JSON", "xpack.enterpriseSearch.appSearch.logRetention.callout.description.manageSettingsLinkText": "設定を表示", @@ -13236,14 +13233,8 @@ "xpack.enterpriseSearch.appSearch.multiInputRows.inputRowPlaceholder": "値を入力", "xpack.enterpriseSearch.appSearch.multiInputRows.removeValueButtonLabel": "値を削除", "xpack.enterpriseSearch.appSearch.ownerRoleTypeDescription": "所有者はすべての操作を実行できます。アカウントには複数の所有者がいる場合がありますが、一度に少なくとも1人以上の所有者が必要です。", - "xpack.enterpriseSearch.appSearch.productCardCTA": "App Searchを開く", - "xpack.enterpriseSearch.appSearch.productCardDescription": "WebサイトとWebサイトに最適なApp Searchでは、強力な検索エクスペリエンスを設計、デプロイ、管理できます。", "xpack.enterpriseSearch.appSearch.productDescription": "ダッシュボード、分析、APIを活用し、高度なアプリケーション検索をシンプルにします。", "xpack.enterpriseSearch.appSearch.productName": "App Search", - "xpack.enterpriseSearch.appSearch.resources.adaptiveRelevanceLabel": "Adaptive Relevanceで自動化", - "xpack.enterpriseSearch.appSearch.resources.gettingStartedLabel": "App Searchの基本操作", - "xpack.enterpriseSearch.appSearch.resources.searchRelevanceLabel": "検索関連性の調整", - "xpack.enterpriseSearch.appSearch.resources.searchUILabel": "App Searchの検索UI", "xpack.enterpriseSearch.appSearch.result.documentDetailLink": "ドキュメントの詳細を表示", "xpack.enterpriseSearch.appSearch.result.hideAdditionalFields": "追加フィールドを非表示", "xpack.enterpriseSearch.appSearch.roleMappingCreatedMessage": "ロールマッピングが作成されました", @@ -14222,7 +14213,6 @@ "xpack.enterpriseSearch.elasticsearch.features.buildSearchExperiences": "カスタム検索エクスペリエンスを構築", "xpack.enterpriseSearch.elasticsearch.features.buildTooling": "カスタムツールを作成", "xpack.enterpriseSearch.elasticsearch.features.integrate": "データベース、Webサイトなどを統合", - "xpack.enterpriseSearch.elasticsearch.productCardCTA": "セットアップガイドを表示", "xpack.enterpriseSearch.elasticsearch.productCardDescription": "カスタムアプリケーションに最適なElasticsearchでは、非常にカスタマイズ性の高い検索を構築し、多数の異なるインジェスチョン方法を利用できます。", "xpack.enterpriseSearch.elasticsearch.productDescription": "高パフォーマンスで関連性の高い検索エクスペリエンスを作成するための低レベルのツール。", "xpack.enterpriseSearch.elasticsearch.productName": "Elasticsearch", @@ -14425,7 +14415,6 @@ "xpack.enterpriseSearch.nav.enterpriseSearchOverviewTitle": "概要", "xpack.enterpriseSearch.nav.esreTitle": "ESRE", "xpack.enterpriseSearch.nav.searchApplicationsTitle": "検索アプリケーション", - "xpack.enterpriseSearch.nav.searchExperiencesTitle": "検索エクスペリエンス", "xpack.enterpriseSearch.nav.searchIndicesTitle": "インデックス", "xpack.enterpriseSearch.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.notFound.action1": "ダッシュボードに戻す", @@ -14881,9 +14870,6 @@ "xpack.enterpriseSearch.workplaceSearch.explorePlatinumFeatures.link": "プラチナ機能の詳細", "xpack.enterpriseSearch.workplaceSearch.externalConnectorApiKey.label": "コネクターAPIキー", "xpack.enterpriseSearch.workplaceSearch.externalConnectorUrl.label": "コネクターURL", - "xpack.enterpriseSearch.workplaceSearch.features.ingest": "サードパーティソースから取り込む", - "xpack.enterpriseSearch.workplaceSearch.features.managementDashboards": "検索管理ダッシュボード", - "xpack.enterpriseSearch.workplaceSearch.features.searchExperiences": "認証されたユーザーの検索エクスペリエンス", "xpack.enterpriseSearch.workplaceSearch.field.label": "フィールド", "xpack.enterpriseSearch.workplaceSearch.groups.addGroup.heading": "グループを追加", "xpack.enterpriseSearch.workplaceSearch.groups.addGroup.label": "グループ名", @@ -15030,8 +15016,6 @@ "xpack.enterpriseSearch.workplaceSearch.privatePlatinumCallout.text": "非公開ソースにはプラチナライセンスが必要です。", "xpack.enterpriseSearch.workplaceSearch.privateSource.text": "非公開ソース", "xpack.enterpriseSearch.workplaceSearch.privateSources.text": "非公開ソース", - "xpack.enterpriseSearch.workplaceSearch.productCardCTA": "Workplace Searchを開く", - "xpack.enterpriseSearch.workplaceSearch.productCardDescription": "社内チームに最適なWorkplace Searchは、コンテンツをすべて1つの場所に統合します。頻繁に使用される生産性ツールにすぐに接続できます。", "xpack.enterpriseSearch.workplaceSearch.productCta": "Workplace Searchを開く", "xpack.enterpriseSearch.workplaceSearch.productDescription": "仮想ワークプレイスで使用可能な、すべてのドキュメント、ファイル、ソースを検索します。", "xpack.enterpriseSearch.workplaceSearch.productName": "Workplace Search", @@ -15046,9 +15030,6 @@ "xpack.enterpriseSearch.workplaceSearch.remove.button": "削除", "xpack.enterpriseSearch.workplaceSearch.removeField.label": "フィールドの削除", "xpack.enterpriseSearch.workplaceSearch.reset.button": "リセット", - "xpack.enterpriseSearch.workplaceSearch.resources.gettingStartedLabel": "Workplace Searchの基本操作", - "xpack.enterpriseSearch.workplaceSearch.resources.managePermissionsLabel": "アクセス権の管理", - "xpack.enterpriseSearch.workplaceSearch.resources.setUpConnectorsLabel": "コネクターを設定", "xpack.enterpriseSearch.workplaceSearch.roleMapping.adminRoleTypeDescription": "管理者は、コンテンツソース、グループ、ユーザー管理機能など、すべての組織レベルの設定に無制限にアクセスできます。", "xpack.enterpriseSearch.workplaceSearch.roleMapping.allGroupsDescription": "すべてのグループへの割り当てには、後から作成および管理されるすべての現在および将来のグループが含まれます。", "xpack.enterpriseSearch.workplaceSearch.roleMapping.allGroupsLabel": "すべてのグループに割り当て", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e901fddb0b54fa6..b4923e507b936e6 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -13204,9 +13204,6 @@ "xpack.enterpriseSearch.appSearch.enginesOverview.table.column.lastUpdated": "上次更新时间", "xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name": "名称", "xpack.enterpriseSearch.appSearch.enginesOverview.title": "引擎概览", - "xpack.enterpriseSearch.appSearch.features.ingest": "使用网络爬虫、API 或 Elasticsearch 进行采集", - "xpack.enterpriseSearch.appSearch.features.managementDashboards": "搜索管理仪表板", - "xpack.enterpriseSearch.appSearch.features.searchApis": "搜索优化 API", "xpack.enterpriseSearch.appSearch.integrations.jsonDescription": "通过 App Search 搜索您的 JSON 数据。", "xpack.enterpriseSearch.appSearch.integrations.jsonName": "JSON", "xpack.enterpriseSearch.appSearch.logRetention.callout.description.manageSettingsLinkText": "访问您的设置", @@ -13235,14 +13232,8 @@ "xpack.enterpriseSearch.appSearch.multiInputRows.inputRowPlaceholder": "输入值", "xpack.enterpriseSearch.appSearch.multiInputRows.removeValueButtonLabel": "删除值", "xpack.enterpriseSearch.appSearch.ownerRoleTypeDescription": "所有者可以执行任何操作。该帐户可以有很多所有者,但任何时候必须至少有一个所有者。", - "xpack.enterpriseSearch.appSearch.productCardCTA": "打开 App Search", - "xpack.enterpriseSearch.appSearch.productCardDescription": "适用于应用和网站,App Search 将帮助您设计、部署并管理强大的搜索体验。", "xpack.enterpriseSearch.appSearch.productDescription": "利用仪表板、分析和 API 执行高级应用程序搜索简单易行。", "xpack.enterpriseSearch.appSearch.productName": "App Search", - "xpack.enterpriseSearch.appSearch.resources.adaptiveRelevanceLabel": "通过自适应相关性实现自动化", - "xpack.enterpriseSearch.appSearch.resources.gettingStartedLabel": "App Search 入门", - "xpack.enterpriseSearch.appSearch.resources.searchRelevanceLabel": "调整搜索相关性", - "xpack.enterpriseSearch.appSearch.resources.searchUILabel": "App Search 的搜索 UI", "xpack.enterpriseSearch.appSearch.result.documentDetailLink": "访问文档详情", "xpack.enterpriseSearch.appSearch.result.hideAdditionalFields": "隐藏其他字段", "xpack.enterpriseSearch.appSearch.roleMappingCreatedMessage": "您的角色映射已创建", @@ -14221,7 +14212,6 @@ "xpack.enterpriseSearch.elasticsearch.features.buildSearchExperiences": "构建定制搜索体验", "xpack.enterpriseSearch.elasticsearch.features.buildTooling": "构建定制工具", "xpack.enterpriseSearch.elasticsearch.features.integrate": "集成数据库、网站等", - "xpack.enterpriseSearch.elasticsearch.productCardCTA": "查看设置指南", "xpack.enterpriseSearch.elasticsearch.productCardDescription": "适用于专门定制的应用程序,Elasticsearch 将帮助您构建高度可定制的搜索,并提供许多不同的采集方法。", "xpack.enterpriseSearch.elasticsearch.productDescription": "用于打造高效、相关的搜索体验的低级工具。", "xpack.enterpriseSearch.elasticsearch.productName": "Elasticsearch", @@ -14424,7 +14414,6 @@ "xpack.enterpriseSearch.nav.enterpriseSearchOverviewTitle": "概览", "xpack.enterpriseSearch.nav.esreTitle": "ESRE", "xpack.enterpriseSearch.nav.searchApplicationsTitle": "搜索应用程序", - "xpack.enterpriseSearch.nav.searchExperiencesTitle": "搜索体验", "xpack.enterpriseSearch.nav.searchIndicesTitle": "索引", "xpack.enterpriseSearch.nav.workplaceSearchTitle": "Workplace Search", "xpack.enterpriseSearch.notFound.action1": "返回到您的仪表板", @@ -14880,9 +14869,6 @@ "xpack.enterpriseSearch.workplaceSearch.explorePlatinumFeatures.link": "了解白金级功能", "xpack.enterpriseSearch.workplaceSearch.externalConnectorApiKey.label": "连接器 API 密钥", "xpack.enterpriseSearch.workplaceSearch.externalConnectorUrl.label": "连接器 URL", - "xpack.enterpriseSearch.workplaceSearch.features.ingest": "从第三方来源采集", - "xpack.enterpriseSearch.workplaceSearch.features.managementDashboards": "搜索管理仪表板", - "xpack.enterpriseSearch.workplaceSearch.features.searchExperiences": "已通过身份验证的用户的搜索体验", "xpack.enterpriseSearch.workplaceSearch.field.label": "字段", "xpack.enterpriseSearch.workplaceSearch.groups.addGroup.heading": "添加组", "xpack.enterpriseSearch.workplaceSearch.groups.addGroup.label": "组名", @@ -15029,8 +15015,6 @@ "xpack.enterpriseSearch.workplaceSearch.privatePlatinumCallout.text": "专用源需要白金级许可证。", "xpack.enterpriseSearch.workplaceSearch.privateSource.text": "专用源", "xpack.enterpriseSearch.workplaceSearch.privateSources.text": "专用源", - "xpack.enterpriseSearch.workplaceSearch.productCardCTA": "Workplace Search", - "xpack.enterpriseSearch.workplaceSearch.productCardDescription": "适用于内部团队,Workplace Search 有助于通过即时连接到常见生产力工具,在一个位置整合您的内容。", "xpack.enterpriseSearch.workplaceSearch.productCta": "Workplace Search", "xpack.enterpriseSearch.workplaceSearch.productDescription": "搜索整个虚拟工作区中存在的所有文档、文件和源。", "xpack.enterpriseSearch.workplaceSearch.productName": "Workplace Search", @@ -15045,9 +15029,6 @@ "xpack.enterpriseSearch.workplaceSearch.remove.button": "移除", "xpack.enterpriseSearch.workplaceSearch.removeField.label": "移除字段", "xpack.enterpriseSearch.workplaceSearch.reset.button": "重置", - "xpack.enterpriseSearch.workplaceSearch.resources.gettingStartedLabel": "Workplace Search 入门", - "xpack.enterpriseSearch.workplaceSearch.resources.managePermissionsLabel": "管理权限", - "xpack.enterpriseSearch.workplaceSearch.resources.setUpConnectorsLabel": "设置您的连接器", "xpack.enterpriseSearch.workplaceSearch.roleMapping.adminRoleTypeDescription": "管理员对所有组织范围设置(包括内容源、组和用户管理功能)具有完全权限。", "xpack.enterpriseSearch.workplaceSearch.roleMapping.allGroupsDescription": "分配给所有组包括之后创建和管理的所有当前和未来组。", "xpack.enterpriseSearch.workplaceSearch.roleMapping.allGroupsLabel": "分配给所有组", diff --git a/x-pack/test/accessibility/apps/enterprise_search.ts b/x-pack/test/accessibility/apps/enterprise_search.ts index 4c8a926da7d2037..bd6483c12ee6786 100644 --- a/x-pack/test/accessibility/apps/enterprise_search.ts +++ b/x-pack/test/accessibility/apps/enterprise_search.ts @@ -37,12 +37,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { async () => await testSubjects.exists('elasticsearchProductCard') ); await retry.waitFor( - 'App Search product card visible', - async () => await testSubjects.exists('appSearchProductCard') + 'Search Applications product card visible', + async () => await testSubjects.exists('enterpriseSearchApplicationsProductCard') ); await retry.waitFor( - 'Workplace Search product card visible', - async () => await testSubjects.exists('workplaceSearchProductCard') + 'Behavioral Analytics product card visible', + async () => await testSubjects.exists('enterpriseSearchAnalyticsProductCard') ); await a11y.testAppSnapshot(); }); @@ -112,5 +112,58 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); }); + + describe('Search Applications', () => { + before(async () => { + await common.navigateToApp('enterprise_search/applications'); + }); + + it('loads search applications list', async function () { + await retry.waitFor( + 'search apps docs link', + async () => await testSubjects.exists('search-applications-documentation-link') + ); + await a11y.testAppSnapshot(); + }); + }); + describe('Behavioral Analytics', () => { + before(async () => { + await common.navigateToApp('enterprise_search/analytics'); + }); + + it('loads Behavioral Analytics page', async function () { + await retry.waitFor( + 'create collections button', + async () => await testSubjects.exists('create-analytics-collection-btn') + ); + await a11y.testAppSnapshot(); + }); + }); + describe('Vector Search', () => { + before(async () => { + await common.navigateToApp('enterprise_search/vector_search'); + }); + + it('loads Vector Search page', async function () { + await retry.waitFor( + 'vector search documentation link', + async () => await testSubjects.exists('vector-search-documentation-link') + ); + await a11y.testAppSnapshot(); + }); + }); + describe('ESRE', () => { + before(async () => { + await common.navigateToApp('enterprise_search/esre'); + }); + + it('loads ESRE page', async function () { + await retry.waitFor( + 'esre header description', + async () => await testSubjects.exists('esre-description-text') + ); + await a11y.testAppSnapshot(); + }); + }); }); } From 7f002de7060bfff26e1f592863846b8c149418b2 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Tue, 25 Jul 2023 16:15:44 +0200 Subject: [PATCH 15/29] =?UTF-8?q?[Security=20Solution]=20Refactor=20ShowTo?= =?UTF-8?q?pN=20Action=20so=20it=20doesn=E2=80=99t=20depend=20on=20App=20c?= =?UTF-8?q?ontext=20providers=20(#161550)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary ### Context: `TopN`components need the application context to work. So, `showTopN` actions wrap the `TopN` component on a custom copy of the entire application context. That is very error-prone and not performative. ### Solution: * Create a service that the actions have access to * Update the action code to call the service * Move the rendering of `TopN` to the App rendering tree and listen to the service for changes ### How to test it? * Hover fields and use `showTopN` actions on different pages Screenshot 2023-07-10 at 16 41 13 Screenshot 2023-07-10 at 16 40 38 Screenshot 2023-07-10 at 16 40 18 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../public/actions/register.ts | 2 +- .../cell_action/show_top_n.test.tsx | 27 ++----- .../show_top_n/cell_action/show_top_n.tsx | 57 +++---------- .../show_top_n/show_top_n_component.test.tsx | 78 ------------------ .../show_top_n/show_top_n_component.tsx | 61 -------------- .../top_values_popover.test.tsx | 81 +++++++++++++++++++ .../top_values_popover/top_values_popover.tsx | 53 ++++++++++++ .../top_values_popover_service.ts | 34 ++++++++ .../public/app/home/index.test.tsx | 12 ++- .../public/app/home/index.tsx | 2 + .../security_solution/public/plugin.tsx | 2 + .../plugins/security_solution/public/types.ts | 2 + 12 files changed, 201 insertions(+), 210 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.tsx create mode 100644 x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.test.tsx create mode 100644 x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx create mode 100644 x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover_service.ts diff --git a/x-pack/plugins/security_solution/public/actions/register.ts b/x-pack/plugins/security_solution/public/actions/register.ts index 2b11301ff64aeba..fc0267243c455e1 100644 --- a/x-pack/plugins/security_solution/public/actions/register.ts +++ b/x-pack/plugins/security_solution/public/actions/register.ts @@ -103,7 +103,7 @@ const registerCellActions = ( filterOut: createFilterOutCellActionFactory({ store, services }), addToTimeline: createAddToTimelineCellActionFactory({ store, services }), investigateInNewTimeline: createInvestigateInNewTimelineCellActionFactory({ store, services }), - showTopN: createShowTopNCellActionFactory({ store, history, services }), + showTopN: createShowTopNCellActionFactory({ services }), copyToClipboard: createCopyToClipboardCellActionFactory({ services }), toggleColumn: createToggleColumnCellActionFactory({ store }), }; diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx index 87c920e78789538..0fb5552eb1e54b2 100644 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx +++ b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx @@ -6,36 +6,24 @@ */ import type { CellActionExecutionContext } from '@kbn/cell-actions'; -import { - createSecuritySolutionStorageMock, - kibanaObservable, - mockGlobalState, - SUB_PLUGINS_REDUCER, -} from '../../../common/mock'; -import { mockHistory } from '../../../common/mock/router'; -import { createStore } from '../../../common/store'; + import { createShowTopNCellActionFactory } from './show_top_n'; -import React from 'react'; import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; +import type { StartServices } from '../../../types'; jest.mock('../../../common/lib/kibana'); -jest.mock('../show_top_n_component', () => ({ - TopNAction: () => {'TEST COMPONENT'}, -})); - -const mockServices = createStartServicesMock(); -const { storage } = createSecuritySolutionStorageMock(); -const mockStore = createStore(mockGlobalState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); +const mockServices = { + ...createStartServicesMock(), + topValuesPopover: { showPopover: jest.fn() }, +} as unknown as StartServices; const element = document.createElement('div'); document.body.appendChild(element); describe('createShowTopNCellActionFactory', () => { const showTopNActionFactory = createShowTopNCellActionFactory({ - store: mockStore, - history: mockHistory, services: mockServices, }); const showTopNAction = showTopNActionFactory({ id: 'testAction' }); @@ -125,7 +113,8 @@ describe('createShowTopNCellActionFactory', () => { describe('execute', () => { it('should execute normally', async () => { await showTopNAction.execute(context); - expect(document.body.textContent).toContain('TEST COMPONENT'); + + expect(mockServices.topValuesPopover.showPopover).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx index 3491f0ffcc620ad..16916fc6ac00a78 100644 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx +++ b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx @@ -4,20 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; -import ReactDOM, { unmountComponentAtNode } from 'react-dom'; -import type { History } from 'history'; -import { Provider } from 'react-redux'; -import { Router } from '@kbn/shared-ux-router'; import { i18n } from '@kbn/i18n'; import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions'; -import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { isDataViewFieldSubtypeNested } from '@kbn/es-query'; -import { KibanaContextProvider } from '../../../common/lib/kibana'; -import { APP_NAME, DEFAULT_DARK_MODE } from '../../../../common/constants'; -import type { SecurityAppStore } from '../../../common/store'; +import { first } from 'lodash/fp'; import { fieldHasCellActions } from '../../utils'; -import { TopNAction } from '../show_top_n_component'; import type { StartServices } from '../../../types'; import type { SecurityCellAction } from '../../types'; import { SecurityCellActionType } from '../../constants'; @@ -32,15 +23,7 @@ const SHOW_TOP = (fieldName: string) => const ICON = 'visBarVertical'; export const createShowTopNCellActionFactory = createCellActionFactory( - ({ - store, - history, - services, - }: { - store: SecurityAppStore; - history: History; - services: StartServices; - }): CellActionTemplate => ({ + ({ services }: { services: StartServices }): CellActionTemplate => ({ type: SecurityCellActionType.SHOW_TOP_N, getIconType: () => ICON, getDisplayName: ({ data }) => SHOW_TOP(data[0]?.field.name), @@ -57,34 +40,14 @@ export const createShowTopNCellActionFactory = createCellActionFactory( ); }, execute: async (context) => { - if (!context.nodeRef.current) return; - - const node = document.createElement('div'); - document.body.appendChild(node); - - const onClose = () => { - unmountComponentAtNode(node); - document.body.removeChild(node); - }; - - const element = ( - - - - - - - - - - ); - - ReactDOM.render(element, node); + const firstItem = first(context.data); + if (!context.nodeRef.current || !firstItem) return; + + services.topValuesPopover.showPopover({ + fieldName: firstItem.field.name, + scopeId: context.metadata?.scopeId, + nodeRef: context.nodeRef.current, + }); }, }) ); diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.test.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.test.tsx deleted file mode 100644 index dc2dd253d18cfd8..000000000000000 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.test.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 { render } from '@testing-library/react'; -import React from 'react'; -import { mockCasesContext } from '@kbn/cases-plugin/public/mocks/mock_cases_context'; -import { TestProviders } from '../../common/mock'; -import { TopNAction } from './show_top_n_component'; -import type { CellActionExecutionContext } from '@kbn/cell-actions'; -import type { CasesUiStart } from '@kbn/cases-plugin/public'; - -jest.mock('react-router-dom', () => { - const original = jest.requireActual('react-router-dom'); - return { - ...original, - useLocation: jest.fn().mockReturnValue({ pathname: '/test' }), - }; -}); -jest.mock('../../common/components/visualization_actions/actions'); -jest.mock('../../common/components/visualization_actions/lens_embeddable'); - -const casesService = { - ui: { getCasesContext: () => mockCasesContext }, -} as unknown as CasesUiStart; - -const element = document.createElement('div'); -document.body.appendChild(element); - -const context = { - data: [ - { - value: 'the-value', - field: { - name: 'user.name', - type: 'keyword', - searchable: true, - aggregatable: true, - }, - }, - ], - trigger: { id: 'trigger' }, - nodeRef: { - current: element, - }, - metadata: undefined, -} as CellActionExecutionContext; - -describe('TopNAction', () => { - it('renders', () => { - const { getByTestId } = render( - {}} context={context} casesService={casesService} />, - { - wrapper: TestProviders, - } - ); - - expect(getByTestId('topN-container')).toBeInTheDocument(); - }); - - it('does not render when nodeRef is null', () => { - const { queryByTestId } = render( - {}} - context={{ ...context, nodeRef: { current: null } }} - casesService={casesService} - />, - { - wrapper: TestProviders, - } - ); - - expect(queryByTestId('topN-container')).not.toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.tsx deleted file mode 100644 index 7dced03bb40d444..000000000000000 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.tsx +++ /dev/null @@ -1,61 +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 { EuiWrappingPopover } from '@elastic/eui'; - -import { useLocation } from 'react-router-dom'; -import type { CasesUiStart } from '@kbn/cases-plugin/public'; -import { first } from 'lodash/fp'; -import { StatefulTopN } from '../../common/components/top_n'; -import { useGetUserCasesPermissions } from '../../common/lib/kibana'; -import { APP_ID } from '../../../common/constants'; -import { getScopeFromPath, useSourcererDataView } from '../../common/containers/sourcerer'; -import type { SecurityCellActionExecutionContext } from '../types'; - -export const TopNAction = ({ - onClose, - context, - casesService, -}: { - onClose: () => void; - context: SecurityCellActionExecutionContext; - casesService: CasesUiStart; -}) => { - const { pathname } = useLocation(); - const { browserFields, indexPattern } = useSourcererDataView(getScopeFromPath(pathname)); - const userCasesPermissions = useGetUserCasesPermissions(); - const CasesContext = casesService.ui.getCasesContext(); - const { data, nodeRef, metadata } = context; - const firstItem = first(data); - - if (!nodeRef?.current || !firstItem) return null; - - return ( - - - - - - ); -}; diff --git a/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.test.tsx b/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.test.tsx new file mode 100644 index 000000000000000..80b22c42b544efc --- /dev/null +++ b/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.test.tsx @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render } from '@testing-library/react'; +import React from 'react'; +import { TestProviders } from '../../../common/mock'; +import { TopValuesPopover } from './top_values_popover'; + +jest.mock('../../../common/components/visualization_actions/lens_embeddable'); +jest.mock('react-router-dom', () => { + const original = jest.requireActual('react-router-dom'); + return { + ...original, + useLocation: jest.fn().mockReturnValue({ pathname: '/test' }), + }; +}); + +const element = document.createElement('button'); +document.body.appendChild(element); + +const data = { + fieldName: 'user.name', + nodeRef: element, +}; + +const mockUseObservable = jest.fn(); + +jest.mock('react-use', () => ({ + ...jest.requireActual('react-use'), + useObservable: () => mockUseObservable(), +})); + +jest.mock('../../../common/lib/kibana', () => { + const original = jest.requireActual('../../../common/lib/kibana'); + return { + ...original, + useKibana: () => ({ + ...original.useKibana(), + services: { + ...original.useKibana().services, + topValuesPopover: { getObservable: jest.fn() }, + }, + }), + }; +}); + +describe('TopNAction', () => { + it('renders', async () => { + mockUseObservable.mockReturnValue(data); + + const { queryByTestId } = render(, { + wrapper: TestProviders, + }); + + expect(queryByTestId('topN-container')).toBeInTheDocument(); + }); + + it('does not render when nodeRef is null', () => { + mockUseObservable.mockReturnValue({ ...data, nodeRef: undefined }); + + const { queryByTestId } = render(, { + wrapper: TestProviders, + }); + + expect(queryByTestId('topN-container')).not.toBeInTheDocument(); + }); + + it('does not render when data is undefined', () => { + mockUseObservable.mockReturnValue(undefined); + + const { queryByTestId } = render(, { + wrapper: TestProviders, + }); + + expect(queryByTestId('topN-container')).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx b/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx new file mode 100644 index 000000000000000..111033bb9b290c4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback } from 'react'; +import { EuiWrappingPopover } from '@elastic/eui'; +import { useLocation } from 'react-router-dom'; +import { useObservable } from 'react-use'; +import { StatefulTopN } from '../../../common/components/top_n'; +import { getScopeFromPath, useSourcererDataView } from '../../../common/containers/sourcerer'; +import { useKibana } from '../../../common/lib/kibana'; + +export const TopValuesPopover = React.memo(() => { + const { pathname } = useLocation(); + const { browserFields, indexPattern } = useSourcererDataView(getScopeFromPath(pathname)); + const { + services: { topValuesPopover }, + } = useKibana(); + const data = useObservable(topValuesPopover.getObservable()); + + const onClose = useCallback(() => { + topValuesPopover.closePopover(); + }, [topValuesPopover]); + + if (!data || !data.nodeRef) return null; + + return ( + + + + ); +}); + +TopValuesPopover.displayName = 'TopValuesPopover'; diff --git a/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover_service.ts b/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover_service.ts new file mode 100644 index 000000000000000..2dd3b816d45fe2f --- /dev/null +++ b/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover_service.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 { BehaviorSubject } from 'rxjs'; + +interface TopValuesData { + fieldName: string; + scopeId?: string; + nodeRef: HTMLElement; +} + +export class TopValuesPopoverService { + private currentPopoverSubject$: BehaviorSubject; + + constructor() { + this.currentPopoverSubject$ = new BehaviorSubject(undefined); + } + + showPopover(data: TopValuesData) { + return this.currentPopoverSubject$.next(data); + } + + closePopover() { + return this.currentPopoverSubject$.next(undefined); + } + + getObservable() { + return this.currentPopoverSubject$.asObservable(); + } +} 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 831f42ae1f2ee47..83ac458032c2cab 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 @@ -33,6 +33,7 @@ import type { TimelineUrl } from '../../timelines/store/timeline/model'; import { timelineDefaults } from '../../timelines/store/timeline/defaults'; import { URL_PARAM_KEY } from '../../common/hooks/use_url_state'; import { InputsModelId } from '../../common/store/inputs/constants'; +import { TopValuesPopoverService } from '../components/top_values_popover/top_values_popover_service'; jest.mock('../../common/store/inputs/actions'); @@ -95,11 +96,11 @@ jest.mock('../../timelines/components/open_timeline/helpers', () => { }; }); -const mockGetTimiline = jest.fn(); +const mockGetTimeline = jest.fn(); jest.mock('../../timelines/store/timeline', () => ({ timelineSelectors: { - getTimelineByIdSelector: () => mockGetTimiline, + getTimelineByIdSelector: () => mockGetTimeline, }, })); @@ -124,6 +125,8 @@ const dummyFilter: Filter = { }, }; +const mockTopValuesPopoverService = new TopValuesPopoverService(); + jest.mock('../../common/lib/kibana', () => { const original = jest.requireActual('../../common/lib/kibana'); return { @@ -132,6 +135,7 @@ jest.mock('../../common/lib/kibana', () => { ...original.useKibana(), services: { ...original.useKibana().services, + topValuesPopover: mockTopValuesPopoverService, data: { ...original.useKibana().services.data, dataViews: { @@ -641,7 +645,7 @@ describe('HomePage', () => { const { rerender } = render(); jest.clearAllMocks(); - mockGetTimiline.mockReturnValue({ ...timelineDefaults, savedObjectId: null }); + mockGetTimeline.mockReturnValue({ ...timelineDefaults, savedObjectId: null }); rerender(); @@ -669,7 +673,7 @@ describe('HomePage', () => { const { rerender } = render(); jest.clearAllMocks(); - mockGetTimiline.mockReturnValue({ ...timelineDefaults, savedObjectId }); + mockGetTimeline.mockReturnValue({ ...timelineDefaults, savedObjectId }); rerender(); 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 5e2bf8796192700..1e98b1c438957d7 100644 --- a/x-pack/plugins/security_solution/public/app/home/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/index.tsx @@ -28,6 +28,7 @@ import { useUpdateBrowserTitle } from '../../common/hooks/use_update_browser_tit import { useUpdateExecutionContext } from '../../common/hooks/use_update_execution_context'; import { useUpgradeSecurityPackages } from '../../detection_engine/rule_management/logic/use_upgrade_security_packages'; import { useSetupDetectionEngineHealthApi } from '../../detection_engine/rule_monitoring'; +import { TopValuesPopover } from '../components/top_values_popover/top_values_popover'; interface HomePageProps { children: React.ReactNode; @@ -61,6 +62,7 @@ const HomePageComponent: React.FC = ({ children, setHeaderActionM {children} + diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index caa9dc3735e99a0..e52273785ea1ba0 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -54,6 +54,7 @@ import { LazyEndpointCustomAssetsExtension } from './management/pages/policy/vie import type { SecurityAppStore } from './common/store/types'; import { PluginContract } from './plugin_contract'; +import { TopValuesPopoverService } from './app/components/top_values_popover/top_values_popover_service'; export class Plugin implements IPlugin { /** @@ -195,6 +196,7 @@ export class Plugin implements IPlugin Date: Tue, 25 Jul 2023 16:24:17 +0200 Subject: [PATCH 16/29] [Lens] unnecessary unsavedChanges badge on dashboard for text based (#162482) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary When you have a text based visualization in a dashboard and you click to edit it, then the unsaved changes badge appears. What happens is we create store, and then we run loadInitial action with the data from the attributes and then the store gets the state from those attributes and pushes the change to the new updater middleware with exactly the same data. It doesn’t affect visualization in any way as the state is correct, but the dashboard thinks there were some changes. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../get_edit_lens_configuration.test.tsx | 86 +++++++++++++++++++ .../get_edit_lens_configuration.tsx | 24 ++++-- 2 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.test.tsx diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.test.tsx b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.test.tsx new file mode 100644 index 000000000000000..34adf0c9c25491f --- /dev/null +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.test.tsx @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockStoreDeps } from '../../../mocks'; +import { + initEmpty, + initExisting, + makeConfigureStore, + setState, + updateDatasourceState, + updateVisualizationState, +} from '../../../state_management'; +import { updatingMiddleware } from './get_edit_lens_configuration'; + +describe('Lens flyout', () => { + let store: ReturnType; + const updaterFn = jest.fn(); + beforeEach(() => { + store = makeConfigureStore(mockStoreDeps(), undefined, updatingMiddleware(updaterFn)); + store.dispatch = jest.fn(store.dispatch); + }); + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('updatingMiddleware for the Lens flyout', () => { + test('updater is not run on store creation', () => { + expect(updaterFn).not.toHaveBeenCalled(); + }); + + test('updater is run if modifies visualization or datasource state', () => { + store.dispatch( + updateDatasourceState({ + datasourceId: 'testDatasource2', + newDatasourceState: 'newDatasourceState', + }) + ); + expect(updaterFn).toHaveBeenCalledWith('newDatasourceState', null); + store.dispatch( + updateVisualizationState({ visualizationId: 'testVis', newState: 'newVisState' }) + ); + expect(updaterFn).toHaveBeenCalledWith('newDatasourceState', 'newVisState'); + }); + + test('updater is not run if it does not modify visualization or datasource state', () => { + // assigning the states to {} to test equality by value check + store.dispatch( + setState({ + datasourceStates: { + testDatasource: { state: {}, isLoading: true }, + testDatasource2: { state: {}, isLoading: true }, + }, + visualization: { state: {}, activeId: 'testVis' }, + }) + ); + updaterFn.mockClear(); + + // testing + store.dispatch( + updateDatasourceState({ + datasourceId: 'testDatasource2', + newDatasourceState: {}, + }) + ); + store.dispatch(updateVisualizationState({ visualizationId: 'testVis', newState: {} })); + expect(updaterFn).not.toHaveBeenCalled(); + }); + test('updater is not run on store initialization actions', () => { + store.dispatch( + initEmpty({ + newState: { visualization: { state: {}, activeId: 'testVis' } }, + }) + ); + store.dispatch( + initExisting({ + visualization: { state: {}, activeId: 'testVis' }, + }) + ); + expect(updaterFn).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx index fe1e504637a669c..28e4f84cb211230 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx @@ -15,7 +15,13 @@ import type { CoreStart } from '@kbn/core/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { isEqual } from 'lodash'; import type { LensPluginStartDependencies } from '../../../plugin'; -import { makeConfigureStore, LensRootStore, loadInitial } from '../../../state_management'; +import { + makeConfigureStore, + LensRootStore, + loadInitial, + initExisting, + initEmpty, +} from '../../../state_management'; import { generateId } from '../../../id_generator'; import type { DatasourceMap, VisualizationMap } from '../../../types'; import { @@ -38,7 +44,8 @@ function LoadingSpinnerWithOverlay() { type UpdaterType = (datasourceState: unknown, visualizationState: unknown) => void; -const updatingMiddleware = +// exported for testing +export const updatingMiddleware = (updater: UpdaterType) => (store: MiddlewareAPI) => (next: Dispatch) => (action: Action) => { const { datasourceStates: prevDatasourceStates, @@ -48,10 +55,17 @@ const updatingMiddleware = next(action); const { datasourceStates, visualization, activeDatasourceId } = store.getState().lens; if ( - !isEqual(prevDatasourceStates, datasourceStates) || - !isEqual(prevVisualization, visualization) || - prevActiveDatasourceId !== activeDatasourceId + prevActiveDatasourceId !== activeDatasourceId || + !isEqual( + prevDatasourceStates[prevActiveDatasourceId].state, + datasourceStates[activeDatasourceId].state + ) || + !isEqual(prevVisualization, visualization) ) { + // ignore the actions that initialize the store with the state from the attributes + if (initExisting.match(action) || initEmpty.match(action)) { + return; + } updater(datasourceStates[activeDatasourceId].state, visualization.state); } }; From 0f7129d678305ee12d168e42d279b875601114f0 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 25 Jul 2023 07:26:16 -0700 Subject: [PATCH 17/29] [DOCS] Automate Observability rules screenshots (#162101) --- .../apps/response_ops_docs/index.ts | 1 + .../observability_alerting/index.ts | 114 ++++++++++++++++++ .../observability_alerting/inventory_rule.ts | 49 ++++++++ .../observability_alerting/list_view.ts | 33 +++++ .../metric_threshold_rule.ts | 63 ++++++++++ 5 files changed, 260 insertions(+) create mode 100644 x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/index.ts create mode 100644 x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/inventory_rule.ts create mode 100644 x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/list_view.ts create mode 100644 x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/metric_threshold_rule.ts diff --git a/x-pack/test/screenshot_creation/apps/response_ops_docs/index.ts b/x-pack/test/screenshot_creation/apps/response_ops_docs/index.ts index 1b241cae30213e5..160b48aa48a87c7 100644 --- a/x-pack/test/screenshot_creation/apps/response_ops_docs/index.ts +++ b/x-pack/test/screenshot_creation/apps/response_ops_docs/index.ts @@ -43,6 +43,7 @@ export default function ({ getPageObject, getService, loadTestFile }: FtrProvide loadTestFile(require.resolve('./stack_cases')); loadTestFile(require.resolve('./stack_connectors')); loadTestFile(require.resolve('./maintenance_windows')); + loadTestFile(require.resolve('./observability_alerting')); loadTestFile(require.resolve('./observability_cases')); loadTestFile(require.resolve('./security_cases')); }); diff --git a/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/index.ts b/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/index.ts new file mode 100644 index 000000000000000..12c4a7fec932ae4 --- /dev/null +++ b/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/index.ts @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 const metricThresholdRuleName = 'network metric packets'; +export const inventoryRuleName = 'CPU'; + +export default function ({ loadTestFile, getService }: FtrProviderContext) { + const browser = getService('browser'); + const actions = getService('actions'); + const rules = getService('rules'); + const emailConnectorName = 'Email connector 1'; + + describe('observability alerting', function () { + let mtRuleId: string; + let invRuleId: string; + let emailConnectorId: string; + before(async () => { + await browser.setWindowSize(1920, 1080); + ({ id: emailConnectorId } = await actions.api.createConnector({ + name: emailConnectorName, + config: { + service: 'other', + from: 'bob@example.com', + host: 'some.non.existent.com', + port: 25, + }, + secrets: { + user: 'bob', + password: 'supersecret', + }, + connectorTypeId: '.email', + })); + ({ id: mtRuleId } = await rules.api.createRule({ + consumer: 'infrastructure', + name: metricThresholdRuleName, + notifyWhen: 'onActionGroupChange', + params: { + criteria: [ + { + aggType: 'max', + comparator: '>', + threshold: [0], + timeSize: 3, + timeUnit: 's', + metric: 'network.packets', + }, + ], + sourceId: 'default', + alertOnNoData: false, + alertOnGroupDisappear: false, + groupBy: ['network.name'], + }, + ruleTypeId: 'metrics.alert.threshold', + schedule: { interval: '1m' }, + actions: [ + { + group: 'metrics.threshold.fired', + id: emailConnectorId, + params: { + level: 'info', + }, + }, + ], + })); + ({ id: invRuleId } = await rules.api.createRule({ + consumer: 'alerts', + name: inventoryRuleName, + notifyWhen: 'onActionGroupChange', + params: { + nodeType: 'host', + criteria: [ + { + comparator: '>', + threshold: [80], + timeSize: 3, + timeUnit: 'm', + metric: 'cpu', + }, + ], + sourceId: 'default', + }, + ruleTypeId: 'metrics.alert.inventory.threshold', + schedule: { interval: '1m' }, + actions: [ + { + group: 'metrics.inventory_threshold.fired', + id: emailConnectorId, + params: { + level: 'info', + }, + }, + ], + })); + }); + + after(async () => { + await rules.api.deleteRule(mtRuleId); + await rules.api.deleteRule(invRuleId); + await rules.api.deleteAllRules(); + await actions.api.deleteConnector(emailConnectorId); + await actions.api.deleteAllConnectors(); + }); + + loadTestFile(require.resolve('./list_view')); + loadTestFile(require.resolve('./inventory_rule')); + loadTestFile(require.resolve('./metric_threshold_rule')); + }); +} diff --git a/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/inventory_rule.ts b/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/inventory_rule.ts new file mode 100644 index 000000000000000..6256e73a91dcbda --- /dev/null +++ b/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/inventory_rule.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { inventoryRuleName } from '.'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const commonScreenshots = getService('commonScreenshots'); + const observability = getService('observability'); + const pageObjects = getPageObjects(['common', 'header']); + const screenshotDirectories = ['response_ops_docs', 'observability_alerting']; + const testSubjects = getService('testSubjects'); + + describe('inventory rule', function () { + it('rule detail screenshots', async () => { + await observability.alerts.common.navigateToRulesPage(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.setValue('ruleSearchField', inventoryRuleName); + const rulesList = await testSubjects.find('rulesList'); + const alertRule = await rulesList.findByCssSelector(`[title="${inventoryRuleName}"]`); + await alertRule.click(); + const actionsButton = await testSubjects.find('actions'); + await actionsButton.click(); + const editButton = await testSubjects.find('editRuleButton'); + await editButton.click(); + const runWhen = await testSubjects.find('addNewActionConnectorActionGroup-0'); + await runWhen.click(); + /* Reposition so that the connector details are visible */ + await testSubjects.scrollIntoView('alertActionAccordion-0'); + await commonScreenshots.takeScreenshot( + 'infrastructure-threshold-run-when-selection', + screenshotDirectories, + 1400, + 1024 + ); + await testSubjects.click('messageAddVariableButton'); + await commonScreenshots.takeScreenshot( + 'infrastructure-threshold-alert-default-message', + screenshotDirectories, + 1400, + 1024 + ); + }); + }); +} diff --git a/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/list_view.ts b/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/list_view.ts new file mode 100644 index 000000000000000..41548a81006792a --- /dev/null +++ b/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/list_view.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 { FtrProviderContext } from '../../../ftr_provider_context'; +import { inventoryRuleName } from '.'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const browser = getService('browser'); + const commonScreenshots = getService('commonScreenshots'); + const observability = getService('observability'); + const pageObjects = getPageObjects(['common', 'header']); + const screenshotDirectories = ['response_ops_docs', 'observability_alerting']; + const testSubjects = getService('testSubjects'); + + describe('list view', function () { + it('observability rules list screenshot', async () => { + await observability.alerts.common.navigateToRulesPage(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.setValue('ruleSearchField', inventoryRuleName); + await browser.pressKeys(browser.keys.ENTER); + await commonScreenshots.takeScreenshot( + 'create-alerts-manage-rules', + screenshotDirectories, + 1400, + 1024 + ); + }); + }); +} diff --git a/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/metric_threshold_rule.ts b/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/metric_threshold_rule.ts new file mode 100644 index 000000000000000..95b2a334bc99259 --- /dev/null +++ b/x-pack/test/screenshot_creation/apps/response_ops_docs/observability_alerting/metric_threshold_rule.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { metricThresholdRuleName } from '.'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const commonScreenshots = getService('commonScreenshots'); + const observability = getService('observability'); + const pageObjects = getPageObjects(['common', 'header']); + const screenshotDirectories = ['response_ops_docs', 'observability_alerting']; + const testSubjects = getService('testSubjects'); + + describe('metric threshold rule', function () { + it('rule detail screenshots', async () => { + await observability.alerts.common.navigateToRulesPage(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.setValue('ruleSearchField', metricThresholdRuleName); + const rulesList = await testSubjects.find('rulesList'); + const alertRule = await rulesList.findByCssSelector(`[title="${metricThresholdRuleName}"]`); + await alertRule.click(); + const actionsButton = await testSubjects.find('actions'); + await actionsButton.click(); + const editButton = await testSubjects.find('editRuleButton'); + await editButton.click(); + const runWhen = await testSubjects.find('addNewActionConnectorActionGroup-0'); + await runWhen.click(); + /* Reposition so that the connector details are visible */ + await testSubjects.scrollIntoView('alertActionAccordion-0'); + await commonScreenshots.takeScreenshot( + 'metrics-threshold-run-when-selection', + screenshotDirectories, + 1400, + 1024 + ); + const notifyWhen = await testSubjects.find('notifyWhenSelect'); + await notifyWhen.click(); + const customInterval = await testSubjects.find('onThrottleInterval'); + await customInterval.click(); + const actionFrequency = await testSubjects.find('summaryOrPerRuleSelect'); + await actionFrequency.click(); + const actionSummary = await testSubjects.find('actionNotifyWhen-option-summary'); + await actionSummary.click(); + await commonScreenshots.takeScreenshot( + 'action-alert-summary', + screenshotDirectories, + 1400, + 1024 + ); + await testSubjects.click('messageAddVariableButton'); + await commonScreenshots.takeScreenshot( + 'metrics-threshold-alert-default-message', + screenshotDirectories, + 1400, + 1024 + ); + }); + }); +} From 492cfdfe3a4b4b827d09986776fb89487e08331b Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 25 Jul 2023 17:56:56 +0200 Subject: [PATCH 18/29] [HTTP] Only allow setting `server.restrictInternalApis` on serverless (#162475) --- .../__snapshots__/http_config.test.ts.snap | 1 - .../src/http_config.test.ts | 28 +++++++++++++++++++ .../src/http_config.ts | 12 ++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/core/http/core-http-server-internal/src/__snapshots__/http_config.test.ts.snap b/packages/core/http/core-http-server-internal/src/__snapshots__/http_config.test.ts.snap index 8df6dd5251c463e..c838892038f2ab6 100644 --- a/packages/core/http/core-http-server-internal/src/__snapshots__/http_config.test.ts.snap +++ b/packages/core/http/core-http-server-internal/src/__snapshots__/http_config.test.ts.snap @@ -77,7 +77,6 @@ Object { "allowFromAnyIp": false, "ipAllowlist": Array [], }, - "restrictInternalApis": false, "rewriteBasePath": false, "securityResponseHeaders": Object { "crossOriginOpenerPolicy": "same-origin", diff --git a/packages/core/http/core-http-server-internal/src/http_config.test.ts b/packages/core/http/core-http-server-internal/src/http_config.test.ts index c535bc64fbb0031..28abe6513ced694 100644 --- a/packages/core/http/core-http-server-internal/src/http_config.test.ts +++ b/packages/core/http/core-http-server-internal/src/http_config.test.ts @@ -509,6 +509,27 @@ describe('versioned', () => { }); }); +describe('restrictInternalApis', () => { + it('is only allowed on serverless', () => { + expect(() => config.schema.validate({ restrictInternalApis: false }, {})).toThrow( + /a value wasn't expected/ + ); + expect(() => config.schema.validate({ restrictInternalApis: true }, {})).toThrow( + /a value wasn't expected/ + ); + expect( + config.schema.validate({ restrictInternalApis: true }, { serverless: true }) + ).toMatchObject({ + restrictInternalApis: true, + }); + }); + it('defaults to false', () => { + expect( + config.schema.validate({ restrictInternalApis: undefined }, { serverless: true }) + ).toMatchObject({ restrictInternalApis: false }); + }); +}); + describe('HttpConfig', () => { it('converts customResponseHeaders to strings or arrays of strings', () => { const httpSchema = config.schema; @@ -535,4 +556,11 @@ describe('HttpConfig', () => { nested: '{"foo":1,"bar":"dolly"}', }); }); + + it('defaults restrictInternalApis to false', () => { + const rawConfig = config.schema.validate({}, {}); + const rawCspConfig = cspConfig.schema.validate({}); + const httpConfig = new HttpConfig(rawConfig, rawCspConfig, ExternalUrlConfig.DEFAULT); + expect(httpConfig.restrictInternalApis).toBe(false); + }); }); diff --git a/packages/core/http/core-http-server-internal/src/http_config.ts b/packages/core/http/core-http-server-internal/src/http_config.ts index d0a3ced0d5fab2b..4cb3d5df0ef0104 100644 --- a/packages/core/http/core-http-server-internal/src/http_config.ts +++ b/packages/core/http/core-http-server-internal/src/http_config.ts @@ -167,7 +167,14 @@ const configSchema = schema.object( }, } ), - restrictInternalApis: schema.boolean({ defaultValue: false }), // allow access to internal routes by default to prevent breaking changes in current offerings + // allow access to internal routes by default to prevent breaking changes in current offerings + restrictInternalApis: schema.conditional( + schema.contextRef('serverless'), + true, + schema.boolean({ defaultValue: false }), + schema.never() + ), + versioned: schema.object({ /** * Which handler resolution algo to use: "newest" or "oldest". @@ -316,7 +323,8 @@ export class HttpConfig implements IHttpConfig { this.requestId = rawHttpConfig.requestId; this.shutdownTimeout = rawHttpConfig.shutdownTimeout; - this.restrictInternalApis = rawHttpConfig.restrictInternalApis; + // default to `false` to prevent breaking changes in current offerings + this.restrictInternalApis = rawHttpConfig.restrictInternalApis ?? false; this.eluMonitor = rawHttpConfig.eluMonitor; this.versioned = rawHttpConfig.versioned; } From 02b04dd2fcedd873bcbe79bf262985902872bd69 Mon Sep 17 00:00:00 2001 From: Luke G <11671118+lgestc@users.noreply.github.com> Date: Tue, 25 Jul 2023 18:21:12 +0200 Subject: [PATCH 19/29] [Serverless] [Security Solution] Add runtime schema for first seen last seen search strategy (#162170) ## Summary This PR adds validation for `firstlastseen` search strategy, as part of https://github.com/elastic/security-team/issues/6486 ### Testing Prerequisites: you have at least one entry on your hosts screen Visit /app/security/hosts/allHosts and click on the first host within the table. The page should render the last seen info. There should be no error notifications rendered. ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- package.json | 3 +- .../first_seen_last_seen.ts | 38 +++++++++ .../common/api/search_strategy/index.ts | 8 ++ .../api/search_strategy/model/filter_query.ts | 83 +++++++++++++++++++ .../common/api/search_strategy/model/order.ts | 12 +++ .../model/request_basic_options.ts | 26 ++++++ .../first_last_seen/index.ts | 19 +---- .../factory/last_first_seen/index.test.ts | 35 ++++++++ .../factory/last_first_seen/index.ts | 10 ++- .../factory/last_first_seen/parse_options.ts | 10 +++ .../query.first_or_last_seen.dsl.ts | 15 ++-- yarn.lock | 5 ++ 12 files changed, 236 insertions(+), 28 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/first_seen_last_seen/first_seen_last_seen.ts create mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/index.ts create mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/model/filter_query.ts create mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/model/order.ts create mode 100644 x-pack/plugins/security_solution/common/api/search_strategy/model/request_basic_options.ts create mode 100644 x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/parse_options.ts diff --git a/package.json b/package.json index 819c6b28a6fdd27..ac13d131ab15a0d 100644 --- a/package.json +++ b/package.json @@ -1008,7 +1008,8 @@ "xstate": "^4.38.1", "xterm": "^5.1.0", "yauzl": "^2.10.0", - "yazl": "^2.5.1" + "yazl": "^2.5.1", + "zod": "^3.21.4" }, "devDependencies": { "@apidevtools/swagger-parser": "^10.0.3", diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/first_seen_last_seen/first_seen_last_seen.ts b/x-pack/plugins/security_solution/common/api/search_strategy/first_seen_last_seen/first_seen_last_seen.ts new file mode 100644 index 000000000000000..d161aac9af18f5c --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/search_strategy/first_seen_last_seen/first_seen_last_seen.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +import type { IKibanaSearchResponse } from '@kbn/data-plugin/common'; + +import { order } from '../model/order'; +import { requestBasicOptionsSchema } from '../model/request_basic_options'; + +export const firstLastSeenRequestOptionsSchema = z + .object({ + order, + field: z.string(), + value: z.string(), + }) + .extend(requestBasicOptionsSchema.partial().shape); + +export type FirstLastSeenRequestOptions = z.infer; + +const inspectSchema = z.object({ + dsl: z.array(z.string()), +}); + +export const firstLastSeenResponseSchema = z + .object({ + firstSeen: z.string().nullable(), + lastSeen: z.string().nullable(), + inspect: inspectSchema, + }) + .partial(); + +export type FirstLastSeenStrategyResponse = z.infer & + IKibanaSearchResponse; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/index.ts b/x-pack/plugins/security_solution/common/api/search_strategy/index.ts new file mode 100644 index 000000000000000..31945f4bbf7ec2c --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/search_strategy/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './first_seen_last_seen/first_seen_last_seen'; diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/model/filter_query.ts b/x-pack/plugins/security_solution/common/api/search_strategy/model/filter_query.ts new file mode 100644 index 000000000000000..89c6e24dad231d8 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/search_strategy/model/filter_query.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +const esMatchQuerySchema = z.object({ + match: z.record( + z.string(), + z.object({ + query: z.string(), + operator: z.string(), + zero_terms_query: z.string(), + }) + ), +}); + +export type ESMatchQuery = z.infer; + +const esQueryStringQuerySchema = z.object({ + query_string: z.object({ + query: z.string(), + analyze_wildcard: z.boolean(), + }), +}); + +export type ESQueryStringQuery = z.infer; + +const esTermQuerySchema = z.object({ + term: z.record(z.string(), z.string()), +}); + +export type ESTermQuery = z.infer; + +const esBoolQuerySchema = z.object({ + bool: z.object({ + filter: z.array(z.object({})), + must: z.array(z.object({})), + must_not: z.array(z.object({})), + should: z.array(z.object({})), + }), +}); + +export type ESBoolQuery = z.infer; + +const esRangeQuerySchema = z.object({ + range: z.record( + z.string(), + z.object({ + gte: z.number(), + lte: z.number(), + format: z.string(), + }) + ), +}); + +export type ESRangeQuery = z.infer; + +const jsonObjectSchema = z.record(z.string(), z.any()); + +export type JsonObject = z.infer; + +export type ESQuery = + | ESRangeQuery + | ESQueryStringQuery + | ESMatchQuery + | ESTermQuery + | ESBoolQuery + | JsonObject; + +const esQuerySchema = z.union([ + esRangeQuerySchema, + esQueryStringQuerySchema, + esMatchQuerySchema, + esTermQuerySchema, + esBoolQuerySchema, + jsonObjectSchema, +]); + +export const filterQuery = z.union([z.string(), z.undefined(), esQuerySchema]); diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/model/order.ts b/x-pack/plugins/security_solution/common/api/search_strategy/model/order.ts new file mode 100644 index 000000000000000..d93aa97188ee2f6 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/search_strategy/model/order.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 { Direction } from '@kbn/timelines-plugin/common'; + +import { z } from 'zod'; + +export const order = z.enum([Direction.asc, Direction.desc]); diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/model/request_basic_options.ts b/x-pack/plugins/security_solution/common/api/search_strategy/model/request_basic_options.ts new file mode 100644 index 000000000000000..49227ac1de509ed --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/search_strategy/model/request_basic_options.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; +import { filterQuery } from './filter_query'; + +export const requestBasicOptionsSchema = z.object({ + timerange: z.object({ + interval: z.string(), + from: z.string(), + to: z.string(), + }), + filterQuery, + defaultIndex: z.array(z.string()), + + // This comes from the IKibanaSearchRequest + factoryQueryType: z.union([z.string(), z.undefined()]), + id: z.union([z.string(), z.undefined()]), + params: z.union([z.object({}), z.undefined()]), +}); + +export type RequestBasicOptions = z.infer; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/first_last_seen/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/first_last_seen/index.ts index 7d161bd73a2ed39..3750345091ee1d5 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/first_last_seen/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/first_last_seen/index.ts @@ -5,20 +5,9 @@ * 2.0. */ -import type { IEsSearchResponse } from '@kbn/data-plugin/common'; - -import type { Inspect, Maybe, Direction } from '../../common'; -import type { RequestBasicOptions } from '../..'; - export const FirstLastSeenQuery = 'firstlastseen'; -export interface FirstLastSeenRequestOptions extends Partial { - order: Direction.asc | Direction.desc; - field: string; - value: string; -} -export interface FirstLastSeenStrategyResponse extends IEsSearchResponse { - inspect?: Maybe; - firstSeen?: Maybe; - lastSeen?: Maybe; -} +export type { + FirstLastSeenRequestOptions, + FirstLastSeenStrategyResponse, +} from '../../../api/search_strategy'; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/index.test.ts index 543af5d9b95bb4b..c8edf6a96b2e2b8 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/index.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/index.test.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { ZodError } from 'zod'; + import type { FirstLastSeenRequestOptions } from '../../../../../common/search_strategy'; import { Direction } from '../../../../../common/search_strategy'; import * as buildQuery from './query.first_or_last_seen.dsl'; @@ -66,6 +68,39 @@ describe('firstLastSeen search strategy', () => { ); expect(result).toMatchObject(formattedSearchStrategyLastResponse); }); + + test('should throw an error when parse fails', async () => { + try { + await firstOrLastSeen.parse( + { invalidOption: 'key' } as unknown as FirstLastSeenRequestOptions, + mockSearchStrategyLastSeenResponse + ); + } catch (error: unknown) { + if (!(error instanceof ZodError)) { + throw error; + } + + expect(error).not.toBeUndefined(); + expect(error.flatten()).toMatchInlineSnapshot(` + Object { + "fieldErrors": Object { + "field": Array [ + "Required", + ], + "order": Array [ + "Required", + ], + "value": Array [ + "Required", + ], + }, + "formErrors": Array [], + } + `); + } + + expect.assertions(2); + }); }); }); }); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/index.ts index 9347f7eda400ca1..396dfed867c18a4 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/index.ts @@ -11,18 +11,18 @@ import type { IEsSearchResponse } from '@kbn/data-plugin/common'; import type { FactoryQueryTypes, FirstLastSeenStrategyResponse, - FirstLastSeenRequestOptions, } from '../../../../../common/search_strategy/security_solution'; import { FirstLastSeenQuery } from '../../../../../common/search_strategy/security_solution'; import { inspectStringifyObject } from '../../../../utils/build_query'; import type { SecuritySolutionFactory } from '../types'; import { buildFirstOrLastSeenQuery } from './query.first_or_last_seen.dsl'; +import { parseOptions } from './parse_options'; export const firstOrLastSeen: SecuritySolutionFactory = { - buildDsl: (options: FirstLastSeenRequestOptions) => buildFirstOrLastSeenQuery(options), + buildDsl: (options: unknown) => buildFirstOrLastSeenQuery(options), parse: async ( - options: FirstLastSeenRequestOptions, + options: unknown, response: IEsSearchResponse ): Promise => { // First try to get the formatted field if it exists or not. @@ -36,7 +36,9 @@ export const firstOrLastSeen: SecuritySolutionFactory dsl: [inspectStringifyObject(buildFirstOrLastSeenQuery(options))], }; - if (options.order === 'asc') { + const { order } = parseOptions(options); + + if (order === 'asc') { return { ...response, inspect, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/parse_options.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/parse_options.ts new file mode 100644 index 000000000000000..604932496230c45 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/parse_options.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { firstLastSeenRequestOptionsSchema } from '../../../../../common/api/search_strategy/first_seen_last_seen/first_seen_last_seen'; + +export const parseOptions = (options: unknown) => firstLastSeenRequestOptionsSchema.parse(options); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/query.first_or_last_seen.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/query.first_or_last_seen.dsl.ts index 1270f3f49909d5f..cee6d19ce54aec6 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/query.first_or_last_seen.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/last_first_seen/query.first_or_last_seen.dsl.ts @@ -5,16 +5,15 @@ * 2.0. */ -import type { FirstLastSeenRequestOptions } from '../../../../../common/search_strategy/security_solution/first_last_seen'; +import type { FirstLastSeenRequestOptions } from '../../../../../common/api/search_strategy/first_seen_last_seen/first_seen_last_seen'; + import { createQueryFilterClauses } from '../../../../utils/build_query'; +import { parseOptions } from './parse_options'; + +export const buildFirstOrLastSeenQuery = (options: unknown) => { + const { field, value, defaultIndex, order, filterQuery }: FirstLastSeenRequestOptions = + parseOptions(options); -export const buildFirstOrLastSeenQuery = ({ - field, - value, - defaultIndex, - order, - filterQuery, -}: FirstLastSeenRequestOptions) => { const filter = [...createQueryFilterClauses(filterQuery), { term: { [field]: value } }]; const dslQuery = { diff --git a/yarn.lock b/yarn.lock index ec7ff3a02eeba6f..93a8c8f47ace03c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30035,6 +30035,11 @@ zip-stream@^4.1.0: compress-commons "^4.1.0" readable-stream "^3.6.0" +zod@^3.21.4: + version "3.21.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db" + integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw== + zwitch@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" From f1fca32d3dd8f045370a2e3dfa79e9c74d60880e Mon Sep 17 00:00:00 2001 From: Giorgos Bamparopoulos Date: Tue, 25 Jul 2023 17:28:30 +0100 Subject: [PATCH 20/29] [APM] Add telemetry for the cardinality of span.destination.service.resource (#162424) Add telemetry about the cardinality of `span.destination.service.resource` within the last day. The indexer will be updated by https://github.com/elastic/telemetry/pull/2402. Closes https://github.com/elastic/kibana/issues/161986 --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__snapshots__/apm_telemetry.test.ts.snap | 10 +++++++ .../collect_data_telemetry/tasks.ts | 30 +++++++++++++++++++ .../apm/server/lib/apm_telemetry/schema.ts | 9 ++++++ .../apm/server/lib/apm_telemetry/types.ts | 1 + .../schema/xpack_plugins.json | 10 +++++++ 5 files changed, 60 insertions(+) diff --git a/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap b/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap index 3c1f38e8a7a1918..daf09c1cae416be 100644 --- a/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap +++ b/x-pack/plugins/apm/common/__snapshots__/apm_telemetry.test.ts.snap @@ -947,6 +947,16 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the } } } + }, + "span_destination_service_resource": { + "properties": { + "1d": { + "type": "long", + "_meta": { + "description": "Total number of unique values of span.destination.service.resource within the last day" + } + } + } } } }, diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts index ce9133ebd8ff72e..a43c67eb6c66d3d 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts @@ -42,6 +42,7 @@ import { TRANSACTION_RESULT, TRANSACTION_TYPE, USER_AGENT_ORIGINAL, + SPAN_DESTINATION_SERVICE_RESOURCE, } from '../../../../common/es_fields/apm'; import { APM_SERVICE_GROUP_SAVED_OBJECT_TYPE, @@ -802,6 +803,32 @@ export const tasks: TelemetryTask[] = [ }, }); + const spanDestinationServiceResourceCount = ( + await telemetryClient.search({ + index: indices.transaction, + body: { + track_total_hits: false, + size: 0, + timeout, + query: { + bool: { + filter: [ + { term: { [PROCESSOR_EVENT]: ProcessorEvent.span } }, + range1d, + ], + }, + }, + }, + aggs: { + span_destination_service_resource: { + cardinality: { + field: SPAN_DESTINATION_SERVICE_RESOURCE, + }, + }, + }, + }) + ).aggregations?.span_destination_service_resource.value; + return { counts: { max_error_groups_per_service: { @@ -823,6 +850,9 @@ export const tasks: TelemetryTask[] = [ servicesAndEnvironmentsCount.aggregations?.service_environments .value || 0, }, + span_destination_service_resource: { + '1d': spanDestinationServiceResourceCount || 0, + }, }, }; }, diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts index 4b6e00c3a18ab9f..e42e9000c592aec 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/schema.ts @@ -211,6 +211,15 @@ export const apmSchema: MakeSchemaFrom = { }, }, }, + span_destination_service_resource: { + '1d': { + ...long, + _meta: { + description: + 'Total number of unique values of span.destination.service.resource within the last day', + }, + }, + }, }, cardinality: { client: { geo: { country_iso_code: { rum: timeframeMap1dSchema } } }, diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts index ae4906feb7c7c6a..790b5bd5702fa5c 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/types.ts @@ -109,6 +109,7 @@ export interface APMUsage { traces: TimeframeMap; services: TimeframeMap; environments: TimeframeMap1d; + span_destination_service_resource: TimeframeMap1d; }; cardinality: { client: { geo: { country_iso_code: { rum: TimeframeMap1d } } }; diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 95c959e473681d2..1b84a9028e7439e 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -4011,6 +4011,16 @@ } } } + }, + "span_destination_service_resource": { + "properties": { + "1d": { + "type": "long", + "_meta": { + "description": "Total number of unique values of span.destination.service.resource within the last day" + } + } + } } } }, From 06fabab55bb07c7c82b0ebed403de6d31cf8abb5 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 25 Jul 2023 10:31:04 -0600 Subject: [PATCH 21/29] Assistant refactor (#162079) --- .../assistant/assistant_header/index.test.tsx | 85 +++++ .../impl/assistant/assistant_header/index.tsx | 139 ++++++++ .../assistant/assistant_title/index.test.tsx | 37 ++ .../impl/assistant/assistant_title/index.tsx | 26 +- .../impl/assistant/block_bot/cta.test.tsx | 48 +++ .../impl/assistant/block_bot/cta.tsx | 52 +++ .../assistant/chat_actions/index.test.tsx | 62 ++++ .../impl/assistant/chat_actions/index.tsx | 68 ++++ .../impl/assistant/chat_send/index.test.tsx | 86 +++++ .../impl/assistant/chat_send/index.tsx | 84 +++++ .../chat_send/use_chat_send.test.tsx | 109 ++++++ .../assistant/chat_send/use_chat_send.tsx | 151 +++++++++ .../impl/assistant/helpers.test.ts | 16 +- .../impl/assistant/helpers.ts | 2 +- .../impl/assistant/index.tsx | 318 +++--------------- .../impl/mock/conversation.ts | 71 ++++ .../impl/mock/system_prompt/index.ts | 10 + .../impl/upgrade/upgrade_buttons.tsx | 2 +- 18 files changed, 1082 insertions(+), 284 deletions(-) create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.test.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/block_bot/cta.test.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/block_bot/cta.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_actions/index.test.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_actions/index.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/index.test.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/index.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.test.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx create mode 100644 x-pack/packages/kbn-elastic-assistant/impl/mock/conversation.ts diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx new file mode 100644 index 000000000000000..59dbbd910548745 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.test.tsx @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { AssistantHeader } from '.'; +import { TestProviders } from '../../mock/test_providers/test_providers'; +import { alertConvo, emptyWelcomeConvo } from '../../mock/conversation'; + +const testProps = { + currentConversation: emptyWelcomeConvo, + currentTitle: { + title: 'Test Title', + titleIcon: 'logoSecurity', + }, + docLinks: { + ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', + DOC_LINK_VERSION: 'master', + }, + isDisabled: false, + isSettingsModalVisible: false, + onConversationSelected: jest.fn(), + onToggleShowAnonymizedValues: jest.fn(), + selectedConversationId: emptyWelcomeConvo.id, + setIsSettingsModalVisible: jest.fn(), + setSelectedConversationId: jest.fn(), + showAnonymizedValues: false, +}; + +describe('AssistantHeader', () => { + it('showAnonymizedValues is not checked when currentConversation.replacements is null', () => { + const { getByText, getByTestId } = render(, { + wrapper: TestProviders, + }); + expect(getByText('Test Title')).toBeInTheDocument(); + expect(getByTestId('showAnonymizedValues')).toHaveAttribute('aria-checked', 'false'); + }); + + it('showAnonymizedValues is not checked when currentConversation.replacements is empty', () => { + const { getByText, getByTestId } = render( + , + { + wrapper: TestProviders, + } + ); + expect(getByText('Test Title')).toBeInTheDocument(); + expect(getByTestId('showAnonymizedValues')).toHaveAttribute('aria-checked', 'false'); + }); + + it('showAnonymizedValues is not checked when currentConversation.replacements has values and showAnonymizedValues is false', () => { + const { getByTestId } = render( + , + { + wrapper: TestProviders, + } + ); + expect(getByTestId('showAnonymizedValues')).toHaveAttribute('aria-checked', 'false'); + }); + + it('showAnonymizedValues is checked when currentConversation.replacements has values and showAnonymizedValues is true', () => { + const { getByTestId } = render( + , + { + wrapper: TestProviders, + } + ); + expect(getByTestId('showAnonymizedValues')).toHaveAttribute('aria-checked', 'true'); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx new file mode 100644 index 000000000000000..eb05133c7083512 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_header/index.tsx @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useMemo } from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiSpacer, + EuiSwitch, + EuiSwitchEvent, + EuiToolTip, +} from '@elastic/eui'; +import { css } from '@emotion/react'; +import { DocLinksStart } from '@kbn/core-doc-links-browser'; +import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/gen_ai/constants'; +import { Conversation } from '../../..'; +import { AssistantTitle } from '../assistant_title'; +import { ConversationSelector } from '../conversations/conversation_selector'; +import { AssistantSettingsButton } from '../settings/assistant_settings_button'; +import * as i18n from '../translations'; + +interface OwnProps { + currentConversation: Conversation; + currentTitle: { title: string | JSX.Element; titleIcon: string }; + defaultConnectorId?: string; + defaultProvider?: OpenAiProviderType; + docLinks: Omit; + isDisabled: boolean; + isSettingsModalVisible: boolean; + onConversationSelected: (cId: string) => void; + onToggleShowAnonymizedValues: (e: EuiSwitchEvent) => void; + selectedConversationId: string; + setIsSettingsModalVisible: React.Dispatch>; + setSelectedConversationId: React.Dispatch>; + shouldDisableKeyboardShortcut?: () => boolean; + showAnonymizedValues: boolean; +} + +type Props = OwnProps; +/** + * Renders the header of the Elastic AI Assistant. + * Provide a user interface for selecting and managing conversations, + * toggling the display of anonymized values, and accessing the assistant settings. + */ +export const AssistantHeader: React.FC = ({ + currentConversation, + currentTitle, + defaultConnectorId, + defaultProvider, + docLinks, + isDisabled, + isSettingsModalVisible, + onConversationSelected, + onToggleShowAnonymizedValues, + selectedConversationId, + setIsSettingsModalVisible, + setSelectedConversationId, + shouldDisableKeyboardShortcut, + showAnonymizedValues, +}) => { + const showAnonymizedValuesChecked = useMemo( + () => + currentConversation.replacements != null && + Object.keys(currentConversation.replacements).length > 0 && + showAnonymizedValues, + [currentConversation.replacements, showAnonymizedValues] + ); + return ( + <> + + + + + + + + + <> + + + + + + + + + + + + + + + + + + ); +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.test.tsx new file mode 100644 index 000000000000000..9bf50e5f084aa29 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.test.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 React from 'react'; +import { render, fireEvent } from '@testing-library/react'; +import { AssistantTitle } from '.'; +import { TestProviders } from '../../mock/test_providers/test_providers'; + +const testProps = { + title: 'Test Title', + titleIcon: 'globe', + docLinks: { ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', DOC_LINK_VERSION: '7.15' }, +}; +describe('AssistantTitle', () => { + it('the component renders correctly with valid props', () => { + const { getByText, container } = render(); + expect(getByText('Test Title')).toBeInTheDocument(); + expect(container.querySelector('[data-euiicon-type="globe"]')).not.toBeNull(); + }); + + it('clicking on the popover button opens the popover with the correct link', () => { + const { getByTestId, queryByTestId } = render(, { + wrapper: TestProviders, + }); + expect(queryByTestId('tooltipContent')).not.toBeInTheDocument(); + fireEvent.click(getByTestId('tooltipIcon')); + expect(getByTestId('tooltipContent')).toBeInTheDocument(); + expect(getByTestId('externalDocumentationLink')).toHaveAttribute( + 'href', + 'https://www.elastic.co/guide/en/security/7.15/security-assistant.html' + ); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx index 150eacd37a6162e..719a02aaee1328f 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/assistant_title/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FunctionComponent, useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { EuiButtonIcon, EuiFlexGroup, @@ -20,10 +20,15 @@ import type { DocLinksStart } from '@kbn/core-doc-links-browser'; import { FormattedMessage } from '@kbn/i18n-react'; import * as i18n from '../translations'; -export const AssistantTitle: FunctionComponent<{ - currentTitle: { title: string | JSX.Element; titleIcon: string }; +/** + * Renders a header title with an icon, a tooltip button, and a popover with + * information about the assistant feature and access to documentation. + */ +export const AssistantTitle: React.FC<{ + title: string | JSX.Element; + titleIcon: string; docLinks: Omit; -}> = ({ currentTitle, docLinks }) => { +}> = ({ title, titleIcon, docLinks }) => { const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = docLinks; const url = `${ELASTIC_WEBSITE_URL}guide/en/security/${DOC_LINK_VERSION}/security-assistant.html`; @@ -54,21 +59,24 @@ export const AssistantTitle: FunctionComponent<{ ), [documentationLink] ); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const onButtonClick = () => setIsPopoverOpen((isOpen: boolean) => !isOpen); - const closePopover = () => setIsPopoverOpen(false); + const onButtonClick = useCallback(() => setIsPopoverOpen((isOpen: boolean) => !isOpen), []); + const closePopover = useCallback(() => setIsPopoverOpen(false), []); + return ( - + - {currentTitle.title} + {title} - +

{i18n.TOOLTIP_TITLE}

{content}

diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/block_bot/cta.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/block_bot/cta.test.tsx new file mode 100644 index 000000000000000..72881ac0bdc9ca4 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/block_bot/cta.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 from 'react'; +import { render } from '@testing-library/react'; +import { BlockBotCallToAction } from './cta'; +import { HttpSetup } from '@kbn/core-http-browser'; + +const testProps = { + connectorPrompt:
{'Connector Prompt'}
, + http: { basePath: { get: jest.fn(() => 'http://localhost:5601') } } as unknown as HttpSetup, + isAssistantEnabled: false, + isWelcomeSetup: false, +}; + +describe('BlockBotCallToAction', () => { + it('UpgradeButtons is rendered when isAssistantEnabled is false and isWelcomeSetup is false', () => { + const { getByTestId, queryByTestId } = render(); + expect(getByTestId('upgrade-buttons')).toBeInTheDocument(); + expect(queryByTestId('connector-prompt')).not.toBeInTheDocument(); + }); + + it('connectorPrompt is rendered when isAssistantEnabled is true and isWelcomeSetup is true', () => { + const props = { + ...testProps, + isAssistantEnabled: true, + isWelcomeSetup: true, + }; + const { getByTestId, queryByTestId } = render(); + expect(getByTestId('connector-prompt')).toBeInTheDocument(); + expect(queryByTestId('upgrade-buttons')).not.toBeInTheDocument(); + }); + + it('null is returned when isAssistantEnabled is true and isWelcomeSetup is false', () => { + const props = { + ...testProps, + isAssistantEnabled: true, + isWelcomeSetup: false, + }; + const { container, queryByTestId } = render(); + expect(container.firstChild).toBeNull(); + expect(queryByTestId('connector-prompt')).not.toBeInTheDocument(); + expect(queryByTestId('upgrade-buttons')).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/block_bot/cta.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/block_bot/cta.tsx new file mode 100644 index 000000000000000..afdb8071eea3ca4 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/block_bot/cta.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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { css } from '@emotion/react'; +import { HttpSetup } from '@kbn/core-http-browser'; +import { UpgradeButtons } from '../../upgrade/upgrade_buttons'; + +interface OwnProps { + connectorPrompt: React.ReactElement; + http: HttpSetup; + isAssistantEnabled: boolean; + isWelcomeSetup: boolean; +} + +type Props = OwnProps; + +/** + * Provides a call-to-action for users to upgrade their subscription or set up a connector + * depending on the isAssistantEnabled and isWelcomeSetup props. + */ +export const BlockBotCallToAction: React.FC = ({ + connectorPrompt, + http, + isAssistantEnabled, + isWelcomeSetup, +}) => { + const basePath = http.basePath.get(); + return !isAssistantEnabled ? ( + + {} + + ) : isWelcomeSetup ? ( + + {connectorPrompt} + + ) : null; +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_actions/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_actions/index.test.tsx new file mode 100644 index 000000000000000..b32febc9a082627 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_actions/index.test.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 { render, fireEvent, within } from '@testing-library/react'; +import { ChatActions } from '.'; + +const onChatCleared = jest.fn(); +const onSendMessage = jest.fn(); +const testProps = { + isDisabled: false, + isLoading: false, + onChatCleared, + onSendMessage, +}; + +describe('ChatActions', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + it('the component renders with all props', () => { + const { getByTestId } = render(); + expect(getByTestId('clear-chat')).toHaveAttribute('aria-label', 'Clear chat'); + expect(getByTestId('submit-chat')).toHaveAttribute('aria-label', 'Submit message'); + }); + + it('onChatCleared function is called when clear chat button is clicked', () => { + const { getByTestId } = render(); + fireEvent.click(getByTestId('clear-chat')); + expect(onChatCleared).toHaveBeenCalled(); + }); + + it('onSendMessage function is called when send message button is clicked', () => { + const { getByTestId } = render(); + + fireEvent.click(getByTestId('submit-chat')); + expect(onSendMessage).toHaveBeenCalled(); + }); + + it('buttons are disabled when isDisabled prop is true', () => { + const props = { + ...testProps, + isDisabled: true, + }; + const { getByTestId } = render(); + expect(getByTestId('clear-chat')).toBeDisabled(); + expect(getByTestId('submit-chat')).toBeDisabled(); + }); + + it('send message button is in loading state when isLoading prop is true', () => { + const props = { + ...testProps, + isLoading: true, + }; + const { getByTestId } = render(); + expect(within(getByTestId('submit-chat')).getByRole('progressbar')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_actions/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_actions/index.tsx new file mode 100644 index 000000000000000..7bb2eec51a9ce34 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_actions/index.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 { css } from '@emotion/react'; +import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; +import { CLEAR_CHAT, SUBMIT_MESSAGE } from '../translations'; + +interface OwnProps { + isDisabled: boolean; + isLoading: boolean; + onChatCleared: () => void; + onSendMessage: () => void; +} + +type Props = OwnProps; +/** + * Renders two EuiButtonIcon components with tooltips for clearing the chat and submitting a message, + * while handling the disabled and loading states of the buttons. + */ +export const ChatActions: React.FC = ({ + isDisabled, + isLoading, + onChatCleared, + onSendMessage, +}) => { + return ( + + + + + + + + + + + + + ); +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/index.test.tsx new file mode 100644 index 000000000000000..bd54136fae4f15d --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/index.test.tsx @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { ChatSend, Props } from '.'; +import { TestProviders } from '../../mock/test_providers/test_providers'; +import { useChatSend } from './use_chat_send'; +import { defaultSystemPrompt, mockSystemPrompt } from '../../mock/system_prompt'; +import { emptyWelcomeConvo } from '../../mock/conversation'; +import { HttpSetup } from '@kbn/core-http-browser'; + +jest.mock('./use_chat_send'); + +const testProps: Props = { + selectedPromptContexts: {}, + allSystemPrompts: [defaultSystemPrompt, mockSystemPrompt], + currentConversation: emptyWelcomeConvo, + http: { + basePath: { + basePath: '/mfg', + serverBasePath: '/mfg', + }, + anonymousPaths: {}, + externalUrl: {}, + } as unknown as HttpSetup, + editingSystemPromptId: defaultSystemPrompt.id, + setEditingSystemPromptId: () => {}, + setPromptTextPreview: () => {}, + setSelectedPromptContexts: () => {}, + setUserPrompt: () => {}, + isDisabled: false, + shouldRefocusPrompt: false, + userPrompt: '', +}; +const handleButtonSendMessage = jest.fn(); +const handleOnChatCleared = jest.fn(); +const handlePromptChange = jest.fn(); +const handleSendMessage = jest.fn(); +const chatSend = { + handleButtonSendMessage, + handleOnChatCleared, + handlePromptChange, + handleSendMessage, + isLoading: false, +}; + +describe('ChatSend', () => { + beforeEach(() => { + jest.clearAllMocks(); + (useChatSend as jest.Mock).mockReturnValue(chatSend); + }); + it('the prompt updates when the text area changes', async () => { + const { getByTestId } = render(, { + wrapper: TestProviders, + }); + const promptTextArea = getByTestId('prompt-textarea'); + const promptText = 'valid prompt text'; + fireEvent.change(promptTextArea, { target: { value: promptText } }); + expect(handlePromptChange).toHaveBeenCalledWith(promptText); + }); + + it('a message is sent when send button is clicked', async () => { + const promptText = 'valid prompt text'; + const { getByTestId } = render(, { + wrapper: TestProviders, + }); + expect(getByTestId('prompt-textarea')).toHaveTextContent(promptText); + fireEvent.click(getByTestId('submit-chat')); + await waitFor(() => { + expect(handleButtonSendMessage).toHaveBeenCalledWith(promptText); + }); + }); + + it('promptValue is set to empty string if isDisabled=true', async () => { + const promptText = 'valid prompt text'; + const { getByTestId } = render(, { + wrapper: TestProviders, + }); + expect(getByTestId('prompt-textarea')).toHaveTextContent(''); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/index.tsx new file mode 100644 index 000000000000000..88db2e124ceab57 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/index.tsx @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useEffect, useMemo, useRef } from 'react'; +import { css } from '@emotion/react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { useChatSend, UseChatSendProps } from './use_chat_send'; +import { ChatActions } from '../chat_actions'; +import { PromptTextArea } from '../prompt_textarea'; + +export interface Props extends UseChatSendProps { + isDisabled: boolean; + shouldRefocusPrompt: boolean; + userPrompt: string | null; +} + +/** + * Renders the user input prompt text area. + * Allows the user to clear the chat and switch between different system prompts. + */ +export const ChatSend: React.FC = ({ + isDisabled, + userPrompt, + shouldRefocusPrompt, + ...rest +}) => { + const { + handleButtonSendMessage, + handleOnChatCleared, + handlePromptChange, + handleSendMessage, + isLoading, + } = useChatSend(rest); + // For auto-focusing prompt within timeline + const promptTextAreaRef = useRef(null); + useEffect(() => { + if (shouldRefocusPrompt && promptTextAreaRef.current) { + promptTextAreaRef?.current.focus(); + } + }, [shouldRefocusPrompt]); + const promptValue = useMemo(() => (isDisabled ? '' : userPrompt ?? ''), [isDisabled, userPrompt]); + + const onSendMessage = useCallback(() => { + handleButtonSendMessage(promptTextAreaRef.current?.value?.trim() ?? ''); + }, [handleButtonSendMessage, promptTextAreaRef]); + + return ( + + + + + + + + + ); +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.test.tsx new file mode 100644 index 000000000000000..5f2f5a4a0c40048 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.test.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 { HttpSetup } from '@kbn/core-http-browser'; +import { useSendMessages } from '../use_send_messages'; +import { useConversation } from '../use_conversation'; +import { emptyWelcomeConvo, welcomeConvo } from '../../mock/conversation'; +import { defaultSystemPrompt, mockSystemPrompt } from '../../mock/system_prompt'; +import { useChatSend, UseChatSendProps } from './use_chat_send'; +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; + +jest.mock('../use_send_messages'); +jest.mock('../use_conversation'); + +const setEditingSystemPromptId = jest.fn(); +const setPromptTextPreview = jest.fn(); +const setSelectedPromptContexts = jest.fn(); +const setUserPrompt = jest.fn(); +const sendMessages = jest.fn(); +const appendMessage = jest.fn(); +const appendReplacements = jest.fn(); +const clearConversation = jest.fn(); + +export const testProps: UseChatSendProps = { + selectedPromptContexts: {}, + allSystemPrompts: [defaultSystemPrompt, mockSystemPrompt], + currentConversation: emptyWelcomeConvo, + http: { + basePath: { + basePath: '/mfg', + serverBasePath: '/mfg', + }, + anonymousPaths: {}, + externalUrl: {}, + } as unknown as HttpSetup, + editingSystemPromptId: defaultSystemPrompt.id, + setEditingSystemPromptId, + setPromptTextPreview, + setSelectedPromptContexts, + setUserPrompt, +}; +const robotMessage = 'Response message from the robot'; +describe('use chat send', () => { + beforeEach(() => { + jest.clearAllMocks(); + (useSendMessages as jest.Mock).mockReturnValue({ + isLoading: false, + sendMessages: sendMessages.mockReturnValue(robotMessage), + }); + (useConversation as jest.Mock).mockReturnValue({ + appendMessage, + appendReplacements, + clearConversation, + }); + }); + it('handleOnChatCleared clears the conversation', () => { + const { result } = renderHook(() => useChatSend(testProps)); + result.current.handleOnChatCleared(); + expect(clearConversation).toHaveBeenCalled(); + expect(setPromptTextPreview).toHaveBeenCalledWith(''); + expect(setUserPrompt).toHaveBeenCalledWith(''); + expect(setSelectedPromptContexts).toHaveBeenCalledWith({}); + expect(clearConversation).toHaveBeenCalledWith(testProps.currentConversation.id); + expect(setEditingSystemPromptId).toHaveBeenCalledWith(defaultSystemPrompt.id); + }); + it('handlePromptChange updates prompt successfully', () => { + const { result } = renderHook(() => useChatSend(testProps)); + result.current.handlePromptChange('new prompt'); + expect(setPromptTextPreview).toHaveBeenCalledWith('new prompt'); + expect(setUserPrompt).toHaveBeenCalledWith('new prompt'); + }); + it('handleButtonSendMessage sends message with context prompt when a valid prompt text is provided', async () => { + const promptText = 'prompt text'; + const { result } = renderHook(() => useChatSend(testProps)); + result.current.handleButtonSendMessage(promptText); + expect(setUserPrompt).toHaveBeenCalledWith(''); + + await waitFor(() => { + expect(sendMessages).toHaveBeenCalled(); + const appendMessageSend = appendMessage.mock.calls[0][0]; + const appendMessageResponse = appendMessage.mock.calls[1][0]; + expect(appendMessageSend.message.content).toEqual( + `You are a helpful, expert assistant who answers questions about Elastic Security. Do not answer questions unrelated to Elastic Security.\nIf you answer a question related to KQL or EQL, it should be immediately usable within an Elastic Security timeline; please always format the output correctly with back ticks. Any answer provided for Query DSL should also be usable in a security timeline. This means you should only ever include the "filter" portion of the query.\nUse the following context to answer questions:\n\n\n\n${promptText}` + ); + expect(appendMessageSend.message.role).toEqual('user'); + expect(appendMessageResponse.message.content).toEqual(robotMessage); + expect(appendMessageResponse.message.role).toEqual('assistant'); + }); + }); + it('handleButtonSendMessage sends message with only provided prompt text and context already exists in convo history', async () => { + const promptText = 'prompt text'; + const { result } = renderHook(() => + useChatSend({ ...testProps, currentConversation: welcomeConvo }) + ); + + result.current.handleButtonSendMessage(promptText); + expect(setUserPrompt).toHaveBeenCalledWith(''); + + await waitFor(() => { + expect(sendMessages).toHaveBeenCalled(); + expect(appendMessage.mock.calls[0][0].message.content).toEqual(`\n\n${promptText}`); + }); + }); +}); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx new file mode 100644 index 000000000000000..3e1c19409788880 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/chat_send/use_chat_send.tsx @@ -0,0 +1,151 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { HttpSetup } from '@kbn/core-http-browser'; +import { SelectedPromptContext } from '../prompt_context/types'; +import { useSendMessages } from '../use_send_messages'; +import { useConversation } from '../use_conversation'; +import { getCombinedMessage } from '../prompt/helpers'; +import { Conversation, Message, Prompt } from '../../..'; +import { getMessageFromRawResponse } from '../helpers'; +import { getDefaultSystemPrompt } from '../use_conversation/helpers'; + +export interface UseChatSendProps { + allSystemPrompts: Prompt[]; + currentConversation: Conversation; + editingSystemPromptId: string | undefined; + http: HttpSetup; + selectedPromptContexts: Record; + setEditingSystemPromptId: React.Dispatch>; + setPromptTextPreview: React.Dispatch>; + setSelectedPromptContexts: React.Dispatch< + React.SetStateAction> + >; + setUserPrompt: React.Dispatch>; +} + +interface UseChatSend { + handleButtonSendMessage: (m: string) => void; + handleOnChatCleared: () => void; + handlePromptChange: (prompt: string) => void; + handleSendMessage: (promptText: string) => void; + isLoading: boolean; +} + +/** + * handles sending messages to an API and updating the conversation state. + * Provides a set of functions that can be used to handle user input, send messages to an API, + * and update the conversation state based on the API response. + */ +export const useChatSend = ({ + allSystemPrompts, + currentConversation, + editingSystemPromptId, + http, + selectedPromptContexts, + setEditingSystemPromptId, + setPromptTextPreview, + setSelectedPromptContexts, + setUserPrompt, +}: UseChatSendProps): UseChatSend => { + const { isLoading, sendMessages } = useSendMessages(); + const { appendMessage, appendReplacements, clearConversation } = useConversation(); + + const handlePromptChange = (prompt: string) => { + setPromptTextPreview(prompt); + setUserPrompt(prompt); + }; + + // Handles sending latest user prompt to API + const handleSendMessage = useCallback( + async (promptText: string) => { + const onNewReplacements = (newReplacements: Record) => + appendReplacements({ + conversationId: currentConversation.id, + replacements: newReplacements, + }); + + const systemPrompt = allSystemPrompts.find((prompt) => prompt.id === editingSystemPromptId); + + const message = await getCombinedMessage({ + isNewChat: currentConversation.messages.length === 0, + currentReplacements: currentConversation.replacements, + onNewReplacements, + promptText, + selectedPromptContexts, + selectedSystemPrompt: systemPrompt, + }); + + const updatedMessages = appendMessage({ + conversationId: currentConversation.id, + message, + }); + + // Reset prompt context selection and preview before sending: + setSelectedPromptContexts({}); + setPromptTextPreview(''); + + const rawResponse = await sendMessages({ + http, + apiConfig: currentConversation.apiConfig, + messages: updatedMessages, + }); + const responseMessage: Message = getMessageFromRawResponse(rawResponse); + appendMessage({ conversationId: currentConversation.id, message: responseMessage }); + }, + [ + allSystemPrompts, + currentConversation, + selectedPromptContexts, + appendMessage, + setSelectedPromptContexts, + setPromptTextPreview, + sendMessages, + http, + appendReplacements, + editingSystemPromptId, + ] + ); + + const handleButtonSendMessage = useCallback( + (message: string) => { + handleSendMessage(message); + setUserPrompt(''); + }, + [handleSendMessage, setUserPrompt] + ); + + const handleOnChatCleared = useCallback(() => { + const defaultSystemPromptId = getDefaultSystemPrompt({ + allSystemPrompts, + conversation: currentConversation, + })?.id; + + setPromptTextPreview(''); + setUserPrompt(''); + setSelectedPromptContexts({}); + clearConversation(currentConversation.id); + setEditingSystemPromptId(defaultSystemPromptId); + }, [ + allSystemPrompts, + clearConversation, + currentConversation, + setEditingSystemPromptId, + setPromptTextPreview, + setSelectedPromptContexts, + setUserPrompt, + ]); + + return { + handleButtonSendMessage, + handleOnChatCleared, + handlePromptChange, + handleSendMessage, + isLoading, + }; +}; diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/helpers.test.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/helpers.test.ts index a6d13bbbfd54449..69bed887e730e22 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/helpers.test.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/helpers.test.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { getDefaultConnector, getWelcomeConversation } from './helpers'; +import { getDefaultConnector, getBlockBotConversation } from './helpers'; import { enterpriseMessaging } from './use_conversation/sample_conversations'; import { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; -describe('getWelcomeConversation', () => { +describe('getBlockBotConversation', () => { describe('isAssistantEnabled = false', () => { const isAssistantEnabled = false; it('When no conversation history, return only enterprise messaging', () => { @@ -19,7 +19,7 @@ describe('getWelcomeConversation', () => { messages: [], apiConfig: {}, }; - const result = getWelcomeConversation(conversation, isAssistantEnabled); + const result = getBlockBotConversation(conversation, isAssistantEnabled); expect(result.messages).toEqual(enterpriseMessaging); expect(result.messages.length).toEqual(1); }); @@ -41,7 +41,7 @@ describe('getWelcomeConversation', () => { ], apiConfig: {}, }; - const result = getWelcomeConversation(conversation, isAssistantEnabled); + const result = getBlockBotConversation(conversation, isAssistantEnabled); expect(result.messages.length).toEqual(2); }); @@ -52,7 +52,7 @@ describe('getWelcomeConversation', () => { messages: enterpriseMessaging, apiConfig: {}, }; - const result = getWelcomeConversation(conversation, isAssistantEnabled); + const result = getBlockBotConversation(conversation, isAssistantEnabled); expect(result.messages.length).toEqual(1); expect(result.messages).toEqual(enterpriseMessaging); }); @@ -75,7 +75,7 @@ describe('getWelcomeConversation', () => { ], apiConfig: {}, }; - const result = getWelcomeConversation(conversation, isAssistantEnabled); + const result = getBlockBotConversation(conversation, isAssistantEnabled); expect(result.messages.length).toEqual(3); }); }); @@ -89,7 +89,7 @@ describe('getWelcomeConversation', () => { messages: [], apiConfig: {}, }; - const result = getWelcomeConversation(conversation, isAssistantEnabled); + const result = getBlockBotConversation(conversation, isAssistantEnabled); expect(result.messages.length).toEqual(3); }); it('returns a conversation history with the welcome conversation appended', () => { @@ -109,7 +109,7 @@ describe('getWelcomeConversation', () => { ], apiConfig: {}, }; - const result = getWelcomeConversation(conversation, isAssistantEnabled); + const result = getBlockBotConversation(conversation, isAssistantEnabled); expect(result.messages.length).toEqual(4); }); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/helpers.ts b/x-pack/packages/kbn-elastic-assistant/impl/assistant/helpers.ts index 7662c749a793138..b01c9001e8319c9 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/helpers.ts +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/helpers.ts @@ -27,7 +27,7 @@ export const getMessageFromRawResponse = (rawResponse: string): Message => { } }; -export const getWelcomeConversation = ( +export const getBlockBotConversation = ( conversation: Conversation, isAssistantEnabled: boolean ): Conversation => { diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx index fd6057e8a2e16a5..2268f8751e64d91 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx @@ -10,12 +10,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, - EuiButtonIcon, - EuiHorizontalRule, EuiCommentList, - EuiToolTip, EuiSwitchEvent, - EuiSwitch, EuiModalFooter, EuiModalHeader, EuiModalBody, @@ -26,28 +22,22 @@ import { css } from '@emotion/react'; import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/gen_ai/constants'; import { ActionConnectorProps } from '@kbn/triggers-actions-ui-plugin/public/types'; +import { ChatSend } from './chat_send'; +import { BlockBotCallToAction } from './block_bot/cta'; +import { AssistantHeader } from './assistant_header'; import { WELCOME_CONVERSATION_TITLE } from './use_conversation/translations'; -import { AssistantTitle } from './assistant_title'; -import { UpgradeButtons } from '../upgrade/upgrade_buttons'; -import { getDefaultConnector, getMessageFromRawResponse, getWelcomeConversation } from './helpers'; +import { getDefaultConnector, getBlockBotConversation } from './helpers'; import { useAssistantContext } from '../assistant_context'; import { ContextPills } from './context_pills'; import { getNewSelectedPromptContext } from '../data_anonymization/get_new_selected_prompt_context'; -import { PromptTextArea } from './prompt_textarea'; import type { PromptContext, SelectedPromptContext } from './prompt_context/types'; import { useConversation } from './use_conversation'; import { CodeBlockDetails, getDefaultSystemPrompt } from './use_conversation/helpers'; -import { useSendMessages } from './use_send_messages'; -import type { Message } from '../assistant_context/types'; -import { ConversationSelector } from './conversations/conversation_selector'; import { PromptEditor } from './prompt_editor'; -import { getCombinedMessage } from './prompt/helpers'; -import * as i18n from './translations'; import { QuickPrompts } from './quick_prompts/quick_prompts'; import { useLoadConnectors } from '../connectorland/use_load_connectors'; import { useConnectorSetup } from '../connectorland/connector_setup'; -import { AssistantSettingsButton } from './settings/assistant_settings_button'; import { ConnectorMissingCallout } from '../connectorland/connector_missing_callout'; export interface Props { @@ -93,9 +83,7 @@ const AssistantComponent: React.FC = ({ [selectedPromptContexts] ); - const { appendMessage, appendReplacements, clearConversation, createConversation } = - useConversation(); - const { isLoading, sendMessages } = useSendMessages(); + const { createConversation } = useConversation(); // Connector details const { @@ -144,8 +132,8 @@ const AssistantComponent: React.FC = ({ // Welcome conversation is a special 'setup' case when no connector exists, mostly extracted to `ConnectorSetup` component, // but currently a bit of state is littered throughout the assistant component. TODO: clean up/isolate this state - const welcomeConversation = useMemo( - () => getWelcomeConversation(currentConversation, isAssistantEnabled), + const blockBotConversation = useMemo( + () => getBlockBotConversation(currentConversation, isAssistantEnabled), [currentConversation, isAssistantEnabled] ); @@ -171,13 +159,16 @@ const AssistantComponent: React.FC = ({ onSetupComplete: () => { bottomRef.current?.scrollIntoView({ behavior: 'auto' }); }, - conversation: welcomeConversation, + conversation: blockBotConversation, isConnectorConfigured: !!connectors?.length, }); const currentTitle: { title: string | JSX.Element; titleIcon: string } = - isWelcomeSetup && welcomeConversation.theme?.title && welcomeConversation.theme?.titleIcon - ? { title: welcomeConversation.theme?.title, titleIcon: welcomeConversation.theme?.titleIcon } + isWelcomeSetup && blockBotConversation.theme?.title && blockBotConversation.theme?.titleIcon + ? { + title: blockBotConversation.theme?.title, + titleIcon: blockBotConversation.theme?.titleIcon, + } : { title, titleIcon: 'logoSecurity' }; const bottomRef = useRef(null); @@ -219,15 +210,6 @@ const AssistantComponent: React.FC = ({ }, []); // End drill in `Add To Timeline` action - // For auto-focusing prompt within timeline - const promptTextAreaRef = useRef(null); - - useEffect(() => { - if (shouldRefocusPrompt && promptTextAreaRef.current) { - promptTextAreaRef?.current.focus(); - } - }, [shouldRefocusPrompt]); - // Scroll to bottom on conversation change useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: 'auto' }); @@ -235,7 +217,6 @@ const AssistantComponent: React.FC = ({ useEffect(() => { setTimeout(() => { bottomRef.current?.scrollIntoView({ behavior: 'auto' }); - promptTextAreaRef?.current?.focus(); }, 0); }, [currentConversation.messages.length, selectedPromptContextsCount]); //// @@ -260,90 +241,10 @@ const AssistantComponent: React.FC = ({ [allSystemPrompts, conversations] ); - const handlePromptChange = useCallback((prompt: string) => { - setPromptTextPreview(prompt); - setUserPrompt(prompt); - }, []); - - // Handles sending latest user prompt to API - const handleSendMessage = useCallback( - async (promptText) => { - const onNewReplacements = (newReplacements: Record) => - appendReplacements({ - conversationId: selectedConversationId, - replacements: newReplacements, - }); - - const systemPrompt = allSystemPrompts.find((prompt) => prompt.id === editingSystemPromptId); - - const message = await getCombinedMessage({ - isNewChat: currentConversation.messages.length === 0, - currentReplacements: currentConversation.replacements, - onNewReplacements, - promptText, - selectedPromptContexts, - selectedSystemPrompt: systemPrompt, - }); - - const updatedMessages = appendMessage({ - conversationId: selectedConversationId, - message, - }); - - // Reset prompt context selection and preview before sending: - setSelectedPromptContexts({}); - setPromptTextPreview(''); - - const rawResponse = await sendMessages({ - http, - apiConfig: currentConversation.apiConfig, - messages: updatedMessages, - }); - const responseMessage: Message = getMessageFromRawResponse(rawResponse); - appendMessage({ conversationId: selectedConversationId, message: responseMessage }); - }, - [ - allSystemPrompts, - currentConversation.messages.length, - currentConversation.replacements, - currentConversation.apiConfig, - selectedPromptContexts, - appendMessage, - selectedConversationId, - sendMessages, - http, - appendReplacements, - editingSystemPromptId, - ] - ); - - const handleButtonSendMessage = useCallback(() => { - handleSendMessage(promptTextAreaRef.current?.value?.trim() ?? ''); - setUserPrompt(''); - }, [handleSendMessage, promptTextAreaRef]); - const handleOnSystemPromptSelectionChange = useCallback((systemPromptId?: string) => { setEditingSystemPromptId(systemPromptId); }, []); - const handleOnChatCleared = useCallback(() => { - const defaultSystemPromptId = getDefaultSystemPrompt({ - allSystemPrompts, - conversation: conversations[selectedConversationId], - })?.id; - - setPromptTextPreview(''); - setUserPrompt(''); - setSelectedPromptContexts({}); - clearConversation(selectedConversationId); - setEditingSystemPromptId(defaultSystemPromptId); - }, [allSystemPrompts, clearConversation, conversations, selectedConversationId]); - - const shouldDisableConversationSelectorHotkeys = useCallback(() => { - const promptTextAreaHasFocus = document.activeElement === promptTextAreaRef.current; - return promptTextAreaHasFocus; - }, [promptTextAreaRef]); - // Add min-height to all codeblocks so timeline icon doesn't overflow const codeBlockContainers = [...document.getElementsByClassName('euiCodeBlock')]; // @ts-ignore-expect-error @@ -398,7 +299,6 @@ const AssistantComponent: React.FC = ({ currentConversation.messages, promptContexts, promptContextId, - handleSendMessage, conversationId, selectedConversationId, selectedPromptContexts, @@ -442,11 +342,11 @@ const AssistantComponent: React.FC = ({ `} /> - {currentConversation.messages.length !== 0 && - Object.keys(selectedPromptContexts).length > 0 && } + {currentConversation.messages.length !== 0 && selectedPromptContextsCount > 0 && ( + + )} - {(currentConversation.messages.length === 0 || - Object.keys(selectedPromptContexts).length > 0) && ( + {(currentConversation.messages.length === 0 || selectedPromptContextsCount > 0) && ( = ({ promptContexts, promptTextPreview, selectedPromptContexts, + selectedPromptContextsCount, showAnonymizedValues, ] ); @@ -504,73 +405,21 @@ const AssistantComponent: React.FC = ({ `} > {showTitle && ( - <> - - - - - - - - - <> - - - - - 0 && - showAnonymizedValues - } - compressed={true} - disabled={currentConversation.replacements == null} - label={i18n.SHOW_ANONYMIZED} - onChange={onToggleShowAnonymizedValues} - /> - - - - - - - - - - - - + )} {/* Create portals for each EuiCodeBlock to add the `Investigate in Timeline` action */} @@ -612,87 +461,26 @@ const AssistantComponent: React.FC = ({ flex-direction: column; `} > - {!isAssistantEnabled ? ( - - - {} - - - ) : ( - isWelcomeSetup && ( - - {connectorPrompt} - - ) - )} - - - - - - - - - - - - - - - - - - - - + + {!isDisabled && ( ( - + Date: Tue, 25 Jul 2023 10:37:29 -0700 Subject: [PATCH 22/29] [Emotion] Order EUI's CSS utilities after Sass styles (#162365) ## Summary Follow up to https://github.com/elastic/kibana/pull/161592 Some remaining EUI components that are still in Sass unfortunately need to respect EUI's global CSS utilities (e.g. `.eui-yScroll`, `.eui-textTruncate` - [full list here](https://elastic.github.io/eui/#/utilities/css-utility-classes)). Creating a separate utilities cache and insertion point should solve the CSS order/specificity issues. ### Checklist - [x] Confirm Emotion output order is expected in head (EUI globals, All Emotion styles, Sass styles, then utilities last) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- packages/core/base/core-base-common/index.ts | 2 +- packages/core/base/core-base-common/src/eui.ts | 1 + .../src/views/template.tsx | 4 +++- .../src/core_theme_provider.tsx | 14 ++++++++++---- packages/kbn-storybook/src/lib/decorators.tsx | 18 ++++++++++++++---- packages/kbn-storybook/tsconfig.json | 1 + .../public/theme/kibana_theme_provider.tsx | 15 +++++++++++---- src/plugins/interactive_setup/tsconfig.json | 1 + .../public/theme/kibana_theme_provider.tsx | 15 +++++++++++---- src/plugins/kibana_react/tsconfig.json | 1 + .../public/theme/kibana_theme_provider.tsx | 15 +++++++++++---- src/plugins/kibana_utils/tsconfig.json | 1 + 12 files changed, 66 insertions(+), 22 deletions(-) diff --git a/packages/core/base/core-base-common/index.ts b/packages/core/base/core-base-common/index.ts index d2f7daafb3341fd..7a89b3990d888c7 100644 --- a/packages/core/base/core-base-common/index.ts +++ b/packages/core/base/core-base-common/index.ts @@ -8,4 +8,4 @@ export type { PluginOpaqueId, PluginName, DiscoveredPlugin } from './src/plugins'; export { PluginType } from './src/plugins'; -export { EUI_STYLES_GLOBAL } from './src/eui'; +export { EUI_STYLES_GLOBAL, EUI_STYLES_UTILS } from './src/eui'; diff --git a/packages/core/base/core-base-common/src/eui.ts b/packages/core/base/core-base-common/src/eui.ts index 8f8ec8585dc1d5e..dc3740ad82a1a49 100644 --- a/packages/core/base/core-base-common/src/eui.ts +++ b/packages/core/base/core-base-common/src/eui.ts @@ -7,3 +7,4 @@ */ export const EUI_STYLES_GLOBAL = 'eui-global'; +export const EUI_STYLES_UTILS = 'eui-utilities'; diff --git a/packages/core/rendering/core-rendering-server-internal/src/views/template.tsx b/packages/core/rendering/core-rendering-server-internal/src/views/template.tsx index bac48c88e1b23be..569c8968a6c3a63 100644 --- a/packages/core/rendering/core-rendering-server-internal/src/views/template.tsx +++ b/packages/core/rendering/core-rendering-server-internal/src/views/template.tsx @@ -8,7 +8,7 @@ import React, { FunctionComponent, createElement } from 'react'; -import { EUI_STYLES_GLOBAL } from '@kbn/core-base-common'; +import { EUI_STYLES_GLOBAL, EUI_STYLES_UTILS } from '@kbn/core-base-common'; import { RenderingMetadata } from '../types'; import { Fonts } from './fonts'; import { Styles } from './styles'; @@ -59,6 +59,8 @@ export const Template: FunctionComponent = ({ {/* Inject stylesheets into the before scripts so that KP plugins with bundled styles will override them */} + {/* Inject EUI CSS utilties after all other styles for CSS specificity */} + {createElement('kbn-csp', { diff --git a/packages/core/theme/core-theme-browser-internal/src/core_theme_provider.tsx b/packages/core/theme/core-theme-browser-internal/src/core_theme_provider.tsx index 1b39d6125e0d189..a0b0d903d999ea9 100644 --- a/packages/core/theme/core-theme-browser-internal/src/core_theme_provider.tsx +++ b/packages/core/theme/core-theme-browser-internal/src/core_theme_provider.tsx @@ -11,7 +11,7 @@ import { Observable } from 'rxjs'; import useObservable from 'react-use/lib/useObservable'; import createCache from '@emotion/cache'; import { EuiProvider } from '@elastic/eui'; -import { EUI_STYLES_GLOBAL } from '@kbn/core-base-common'; +import { EUI_STYLES_GLOBAL, EUI_STYLES_UTILS } from '@kbn/core-base-common'; import type { CoreTheme } from '@kbn/core-theme-browser'; import { convertCoreTheme } from './convert_core_theme'; @@ -25,12 +25,18 @@ interface CoreThemeProviderProps { } const globalCache = createCache({ - key: 'eui', + key: EUI_STYLES_GLOBAL, container: document.querySelector(`meta[name="${EUI_STYLES_GLOBAL}"]`) as HTMLElement, }); +globalCache.compat = true; +const utilitiesCache = createCache({ + key: EUI_STYLES_UTILS, + container: document.querySelector(`meta[name="${EUI_STYLES_UTILS}"]`) as HTMLElement, +}); +utilitiesCache.compat = true; const emotionCache = createCache({ key: 'css', - container: document.querySelector(`meta[name="emotion"]`) as HTMLElement, + container: document.querySelector('meta[name="emotion"]') as HTMLElement, }); emotionCache.compat = true; @@ -52,7 +58,7 @@ export const CoreThemeProvider: FC = ({ utilityClasses={includeGlobalStyles} colorMode={euiTheme.colorMode} theme={euiTheme.euiThemeSystem} - cache={{ default: emotionCache, global: globalCache }} + cache={{ default: emotionCache, global: globalCache, utility: utilitiesCache }} > {children} diff --git a/packages/kbn-storybook/src/lib/decorators.tsx b/packages/kbn-storybook/src/lib/decorators.tsx index 39bfcf6c75e3110..80aa6304e2669b0 100644 --- a/packages/kbn-storybook/src/lib/decorators.tsx +++ b/packages/kbn-storybook/src/lib/decorators.tsx @@ -7,6 +7,7 @@ */ import React from 'react'; +import { EUI_STYLES_GLOBAL, EUI_STYLES_UTILS } from '@kbn/core-base-common'; import { EuiProvider } from '@elastic/eui'; import createCache from '@emotion/cache'; import type { DecoratorFn } from '@storybook/react'; @@ -20,17 +21,26 @@ import 'core_styles'; const EuiProviderDecorator: DecoratorFn = (storyFn, { globals }) => { const colorMode = globals.euiTheme === 'v8.dark' ? 'dark' : 'light'; const globalCache = createCache({ - key: 'eui', - container: document.querySelector(`meta[name="eui-global"]`) as HTMLElement, + key: EUI_STYLES_GLOBAL, + container: document.querySelector(`meta[name="${EUI_STYLES_GLOBAL}"]`) as HTMLElement, }); + globalCache.compat = true; + const utilitiesCache = createCache({ + key: EUI_STYLES_UTILS, + container: document.querySelector(`meta[name="${EUI_STYLES_UTILS}"]`) as HTMLElement, + }); + utilitiesCache.compat = true; const emotionCache = createCache({ key: 'css', - container: document.querySelector(`meta[name="emotion"]`) as HTMLElement, + container: document.querySelector('meta[name="emotion"]') as HTMLElement, }); emotionCache.compat = true; return ( - + {storyFn()} ); diff --git a/packages/kbn-storybook/tsconfig.json b/packages/kbn-storybook/tsconfig.json index 765dd18aee082b4..922f21f90d08c2e 100644 --- a/packages/kbn-storybook/tsconfig.json +++ b/packages/kbn-storybook/tsconfig.json @@ -16,6 +16,7 @@ "@kbn/ui-shared-deps-src", "@kbn/repo-info", "@kbn/dev-cli-runner", + "@kbn/core-base-common", ], "exclude": [ "target/**/*", diff --git a/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx b/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx index 29d2bd893a87d01..e5390fc9393eff5 100644 --- a/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx +++ b/src/plugins/interactive_setup/public/theme/kibana_theme_provider.tsx @@ -14,6 +14,7 @@ import React, { useMemo } from 'react'; import useObservable from 'react-use/lib/useObservable'; import type { Observable } from 'rxjs'; +import { EUI_STYLES_GLOBAL, EUI_STYLES_UTILS } from '@kbn/core-base-common'; import type { CoreTheme } from '@kbn/core/public'; import { getColorMode } from './utils'; @@ -28,12 +29,18 @@ const defaultTheme: CoreTheme = { }; const globalCache = createCache({ - key: 'eui', - container: document.querySelector(`meta[name="eui-styles"]`) as HTMLElement, + key: EUI_STYLES_GLOBAL, + container: document.querySelector(`meta[name="${EUI_STYLES_GLOBAL}"]`) as HTMLElement, }); +globalCache.compat = true; +const utilitiesCache = createCache({ + key: EUI_STYLES_UTILS, + container: document.querySelector(`meta[name="${EUI_STYLES_UTILS}"]`) as HTMLElement, +}); +utilitiesCache.compat = true; const emotionCache = createCache({ key: 'css', - container: document.querySelector(`meta[name="emotion"]`) as HTMLElement, + container: document.querySelector('meta[name="emotion"]') as HTMLElement, }); emotionCache.compat = true; @@ -46,7 +53,7 @@ export const KibanaThemeProvider: FC = ({ theme$, modi return ( = ({ theme$, modi return ( = ({ theme$, modi return ( Date: Tue, 25 Jul 2023 15:34:13 -0400 Subject: [PATCH 23/29] [Ingest Node Pipelines] Implement `EuiInlineEdit` into Inline Text Input Component (#162398) Included in https://github.com/elastic/eui/issues/6778 ## Summary Hi team! EUI recently released the `EuiInlineEdit` component and the Ingest Node Pipelines page was identified as a good candidate for the new component. This PR is replaces the inner workings of the `InlineTextInput` component and replaces it with the new `EuiInlineEdit` component. I've included screens below of this change, but would love to hear your feedback and ensure this component installation meets all of the Ingest Node Pipeline needs. **Ingest Node Pipelines (Read Mode)** ![4ADF42EF-B796-4ACD-918A-164132117166](https://github.com/elastic/kibana/assets/40739624/3d43e45f-9149-4ce8-9f4c-3c7c4bafcc88) **Ingest Node Pipelines (Edit Mode)** ![739AA987-77E3-4D19-B04A-EF97982C41A7](https://github.com/elastic/kibana/assets/40739624/9abddf40-8e76-4c34-b5e8-31578e655f3f) --- Changes I'd like to call out: - There's no tooltip surrounding inline edit that displays the placeholder or text value. `EuiInlineEdit` includes a `title` for the read mode button, so the value can be seen on hover. (This feature will make it into the next Kibana upgrade and will not require any additional changes). - The `placeholder` styling is slightly different than the previous version Design Question: Should the inline edit to be constrained to the left side of the pipeline? I didn't want to change this aspect without prior input. ### Checklist Delete any items that are not applicable to this PR. - ~[ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)~ - ~[ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials~ - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - ~[ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~ - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../inline_text_input.tsx | 106 ------------------ .../pipeline_processors_editor_item.tsx | 16 ++- 2 files changed, 10 insertions(+), 112 deletions(-) delete mode 100644 x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/inline_text_input.tsx diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/inline_text_input.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/inline_text_input.tsx deleted file mode 100644 index 36222eebcea4bd0..000000000000000 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/inline_text_input.tsx +++ /dev/null @@ -1,106 +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 classNames from 'classnames'; -import React, { useState, useEffect, useCallback, memo } from 'react'; -import { EuiFieldText, EuiText, keys, EuiToolTip } from '@elastic/eui'; - -export interface Props { - placeholder: string; - ariaLabel: string; - onChange: (value: string) => void; - /** - * Whether the containing element of the text input can be focused. - * - * If it cannot be focused, this component cannot switch to showing - * the text input field. - * - * Defaults to false. - */ - disabled?: boolean; - text?: string; -} - -function _InlineTextInput({ - placeholder, - text, - ariaLabel, - disabled = false, - onChange, -}: Props): React.ReactElement | null { - const [isShowingTextInput, setIsShowingTextInput] = useState(false); - const [textValue, setTextValue] = useState(() => text ?? ''); - - const containerClasses = classNames('pipelineProcessorsEditor__item__textContainer', { - 'pipelineProcessorsEditor__item__textContainer--notEditing': !isShowingTextInput && !disabled, - }); - - const submitChange = useCallback(() => { - // Give any on blur handlers the chance to complete if the user is - // tabbing over this component. - setTimeout(() => { - setIsShowingTextInput(false); - onChange(textValue); - }); - }, [setIsShowingTextInput, onChange, textValue]); - - useEffect(() => { - setTextValue(text ?? ''); - }, [text]); - - useEffect(() => { - const keyboardListener = (event: KeyboardEvent) => { - if (event.key === keys.ESCAPE || event.code === 'Escape') { - setIsShowingTextInput(false); - } - if (event.key === keys.ENTER || event.code === 'Enter') { - submitChange(); - } - }; - if (isShowingTextInput) { - window.addEventListener('keyup', keyboardListener); - } - return () => { - window.removeEventListener('keyup', keyboardListener); - }; - }, [isShowingTextInput, submitChange, setIsShowingTextInput]); - - return isShowingTextInput && !disabled ? ( -
- el?.focus()} - onChange={(event) => setTextValue(event.target.value)} - /> -
- ) : ( -
setIsShowingTextInput(true)} - > - - -
- {text || {placeholder}} -
-
-
-
- ); -} - -export const InlineTextInput = memo(_InlineTextInput); diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx index 765e1ffcf88e565..9edef3e800a98ec 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/pipeline_processors_editor_item/pipeline_processors_editor_item.tsx @@ -11,6 +11,7 @@ import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, + EuiInlineEditText, EuiLink, EuiLoadingSpinner, EuiPanel, @@ -30,7 +31,6 @@ import { getProcessorDescriptor } from '../shared'; import './pipeline_processors_editor_item.scss'; -import { InlineTextInput } from './inline_text_input'; import { ContextMenu } from './context_menu'; import { i18nTexts } from './i18n_texts'; import { Handlers } from './types'; @@ -213,12 +213,16 @@ export const PipelineProcessorsEditorItem: FunctionComponent = memo( className={inlineTextInputContainerClasses} grow={false} > - { + onDescriptionChange(newTextValue); + }} />
From 8b42e0f79b1dfd6ce81b9f89846eee4d9df21b75 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 25 Jul 2023 21:49:13 +0200 Subject: [PATCH 24/29] [Discover] Make share links and search session info shorter for ad-hoc data views (#161180) - Closes https://github.com/elastic/kibana/issues/160993 ## Summary This PR introduces `dataView.toMinimalSpec()` which is used now in 3 cases: - when constructing an alert link - when constructing a share URL for ad-hoc data views - when constructing search session info for ad-hoc data views --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../src/__mocks__/data_view.ts | 1 + .../__snapshots__/data_view.test.ts.snap | 23 ++++ .../common/data_views/data_view.test.ts | 107 ++++++++++++++++++ .../data_views/common/data_views/data_view.ts | 24 +++- .../components/top_nav/get_top_nav_links.tsx | 2 +- .../main/services/discover_state.test.ts | 2 +- .../main/services/discover_state.ts | 2 +- .../es_query/lib/fetch_search_source_query.ts | 17 +-- .../rule_types/es_query/rule_type.test.ts | 61 +++++----- 9 files changed, 189 insertions(+), 50 deletions(-) diff --git a/packages/kbn-discover-utils/src/__mocks__/data_view.ts b/packages/kbn-discover-utils/src/__mocks__/data_view.ts index b6f86109b580b0f..9175fe655b974bb 100644 --- a/packages/kbn-discover-utils/src/__mocks__/data_view.ts +++ b/packages/kbn-discover-utils/src/__mocks__/data_view.ts @@ -114,6 +114,7 @@ export const buildDataViewMock = ({ isTimeNanosBased: () => false, isPersisted: () => true, toSpec: () => ({}), + toMinimalSpec: () => ({}), getTimeField: () => { return dataViewFields.find((field) => field.name === timeFieldName); }, diff --git a/src/plugins/data_views/common/data_views/__snapshots__/data_view.test.ts.snap b/src/plugins/data_views/common/data_views/__snapshots__/data_view.test.ts.snap index 22e08e1b3f0232e..bfeca0d94262229 100644 --- a/src/plugins/data_views/common/data_views/__snapshots__/data_view.test.ts.snap +++ b/src/plugins/data_views/common/data_views/__snapshots__/data_view.test.ts.snap @@ -26,6 +26,29 @@ Object { } `; +exports[`IndexPattern toMinimalSpec can exclude fields 1`] = ` +Object { + "allowNoIndex": false, + "fieldAttrs": undefined, + "fieldFormats": Object {}, + "id": "test-pattern", + "name": "Name", + "runtimeFieldMap": Object { + "runtime_field": Object { + "script": Object { + "source": "emit('hello world')", + }, + "type": "keyword", + }, + }, + "sourceFilters": Array [], + "timeFieldName": "time", + "title": "title", + "type": "index-pattern", + "version": "2", +} +`; + exports[`IndexPattern toSpec can optionally exclude fields 1`] = ` Object { "allowNoIndex": false, diff --git a/src/plugins/data_views/common/data_views/data_view.test.ts b/src/plugins/data_views/common/data_views/data_view.test.ts index 11176475f7c9520..6b756dffaba2a47 100644 --- a/src/plugins/data_views/common/data_views/data_view.test.ts +++ b/src/plugins/data_views/common/data_views/data_view.test.ts @@ -478,4 +478,111 @@ describe('IndexPattern', () => { expect(dataView1.sourceFilters).not.toBe(dataView2.sourceFilters); }); }); + + describe('toMinimalSpec', () => { + test('can exclude fields', () => { + expect(indexPattern.toMinimalSpec()).toMatchSnapshot(); + }); + + test('can omit counts', () => { + const fieldsMap = { + test1: { + name: 'test1', + type: 'keyword', + aggregatable: true, + searchable: true, + readFromDocValues: false, + }, + test2: { + name: 'test2', + type: 'keyword', + aggregatable: true, + searchable: true, + readFromDocValues: false, + }, + test3: { + name: 'test3', + type: 'keyword', + aggregatable: true, + searchable: true, + readFromDocValues: false, + }, + }; + expect( + create('test', { + id: 'test', + title: 'test*', + fields: fieldsMap, + fieldAttrs: undefined, + }).toMinimalSpec().fieldAttrs + ).toBeUndefined(); + expect( + create('test', { + id: 'test', + title: 'test*', + fields: fieldsMap, + fieldAttrs: { + test1: { + count: 11, + }, + test2: { + count: 12, + }, + }, + }).toMinimalSpec().fieldAttrs + ).toBeUndefined(); + + expect( + create('test', { + id: 'test', + title: 'test*', + fields: fieldsMap, + fieldAttrs: { + test1: { + count: 11, + customLabel: 'test11', + }, + test2: { + count: 12, + }, + }, + }).toMinimalSpec().fieldAttrs + ).toMatchInlineSnapshot(` + Object { + "test1": Object { + "customLabel": "test11", + }, + } + `); + + expect( + create('test', { + id: 'test', + title: 'test*', + fields: fieldsMap, + fieldAttrs: { + test1: { + count: 11, + customLabel: 'test11', + }, + test2: { + customLabel: 'test12', + }, + test3: { + count: 30, + }, + }, + }).toMinimalSpec().fieldAttrs + ).toMatchInlineSnapshot(` + Object { + "test1": Object { + "customLabel": "test11", + }, + "test2": Object { + "customLabel": "test12", + }, + } + `); + }); + }); }); diff --git a/src/plugins/data_views/common/data_views/data_view.ts b/src/plugins/data_views/common/data_views/data_view.ts index 428a5c4321c6ddd..ea0e24ba17271f6 100644 --- a/src/plugins/data_views/common/data_views/data_view.ts +++ b/src/plugins/data_views/common/data_views/data_view.ts @@ -15,7 +15,7 @@ import type { } from '@kbn/field-formats-plugin/common'; import { castEsToKbnFieldTypeName, ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; import { CharacterNotAllowedInField } from '@kbn/kibana-utils-plugin/common'; -import { cloneDeep, each, reject } from 'lodash'; +import { cloneDeep, each, mapValues, omit, pickBy, reject } from 'lodash'; import type { DataViewAttributes, FieldAttrs, FieldAttrSet } from '..'; import type { DataViewField, IIndexPatternFieldList } from '../fields'; import { fieldList } from '../fields'; @@ -332,6 +332,28 @@ export class DataView implements DataViewBase { return Object.fromEntries(Object.entries(spec).filter(([, v]) => typeof v !== 'undefined')); } + /** + * Creates a minimal static representation of the data view. Fields and popularity scores will be omitted. + */ + public toMinimalSpec(): Omit { + // removes `fields` + const dataViewSpec = this.toSpec(false); + + if (dataViewSpec.fieldAttrs) { + // removes `count` props (popularity scores) from `fieldAttrs` + dataViewSpec.fieldAttrs = pickBy( + mapValues(dataViewSpec.fieldAttrs, (fieldAttrs) => omit(fieldAttrs, 'count')), + (trimmedFieldAttrs) => Object.keys(trimmedFieldAttrs).length > 0 + ); + + if (Object.keys(dataViewSpec.fieldAttrs).length === 0) { + dataViewSpec.fieldAttrs = undefined; + } + } + + return dataViewSpec; + } + /** * Get the source filtering configuration for that index. */ diff --git a/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.tsx b/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.tsx index 59b6dd620d2cddc..ba2f3148075ced0 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.tsx @@ -146,7 +146,7 @@ export const getTopNavLinks = ({ ...(savedSearch.id ? { savedSearchId: savedSearch.id } : {}), ...(dataView?.isPersisted() ? { dataViewId: dataView?.id } - : { dataViewSpec: dataView?.toSpec() }), + : { dataViewSpec: dataView?.toMinimalSpec() }), filters, timeRange, refreshInterval, diff --git a/src/plugins/discover/public/application/main/services/discover_state.test.ts b/src/plugins/discover/public/application/main/services/discover_state.test.ts index 6ba600e1f08af2d..6533fd74c1fcefc 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.test.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.test.ts @@ -522,7 +522,7 @@ describe('Test discover state actions', () => { timeFieldName: 'mock-time-field-name', }; const dataViewsCreateMock = discoverServiceMock.dataViews.create as jest.Mock; - dataViewsCreateMock.mockImplementation(() => ({ + dataViewsCreateMock.mockImplementationOnce(() => ({ ...dataViewMock, ...dataViewSpecMock, isPersisted: () => false, diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 857cc2fa9a48625..8e72aba3973dee8 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -540,6 +540,6 @@ function createUrlGeneratorState({ viewMode: appState.viewMode, hideAggregatedPreview: appState.hideAggregatedPreview, breakdownField: appState.breakdownField, - dataViewSpec: !dataView?.isPersisted() ? dataView?.toSpec(false) : undefined, + dataViewSpec: !dataView?.isPersisted() ? dataView?.toMinimalSpec() : undefined, }; } diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.ts index 1ae217f96c32694..dc8a4db2610d75e 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { omit, pickBy, mapValues } from 'lodash'; import { buildRangeFilter, Filter } from '@kbn/es-query'; import { DataView, @@ -221,19 +220,5 @@ function updateFilterReferences(filters: Filter[], fromDataView: string, toDataV export function getSmallerDataViewSpec( dataView: DataView ): DiscoverAppLocatorParams['dataViewSpec'] { - const dataViewSpec = dataView.toSpec(false); - - if (dataViewSpec.fieldAttrs) { - // remove `count` props - dataViewSpec.fieldAttrs = pickBy( - mapValues(dataViewSpec.fieldAttrs, (fieldAttrs) => omit(fieldAttrs, 'count')), - (trimmedFieldAttrs) => Object.keys(trimmedFieldAttrs).length > 0 - ); - - if (Object.keys(dataViewSpec.fieldAttrs).length === 0) { - dataViewSpec.fieldAttrs = undefined; - } - } - - return dataViewSpec; + return dataView.toMinimalSpec(); } diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type.test.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type.test.ts index b6d0e9337506cf5..0cbb2b2213863fe 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type.test.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type.test.ts @@ -14,6 +14,8 @@ import { AlertInstanceMock, } from '@kbn/alerting-plugin/server/mocks'; import { loggingSystemMock } from '@kbn/core/server/mocks'; +import type { DataViewSpec } from '@kbn/data-views-plugin/common'; +import { createStubDataView } from '@kbn/data-views-plugin/common/data_view.stub'; import { getRuleType } from './rule_type'; import { EsQueryRuleParams, EsQueryRuleState } from './rule_type_params'; import { ActionContext } from './action_context'; @@ -512,32 +514,31 @@ describe('ruleType', () => { }); describe('search source query', () => { - const dataViewMock = { - id: 'test-id', - title: 'test-title', - timeFieldName: 'time-field', - fields: [ - { - name: 'message', - type: 'string', - displayName: 'message', - scripted: false, - filterable: false, - aggregatable: false, - }, - { - name: 'timestamp', - type: 'date', - displayName: 'timestamp', - scripted: false, - filterable: false, - aggregatable: false, + const dataViewMock = createStubDataView({ + spec: { + id: 'test-id', + title: 'test-title', + timeFieldName: 'time-field', + fields: { + message: { + name: 'message', + type: 'string', + scripted: false, + searchable: false, + aggregatable: false, + readFromDocValues: false, + }, + timestamp: { + name: 'timestamp', + type: 'date', + scripted: false, + searchable: true, + aggregatable: false, + readFromDocValues: false, + }, }, - ], - toSpec: () => { - return { id: 'test-id', title: 'test-title', timeFieldName: 'time-field' }; }, - }; + }); const defaultParams: OnlySearchSourceRuleParams = { size: 100, timeWindowSize: 5, @@ -583,9 +584,9 @@ describe('ruleType', () => { const searchResult: ESSearchResponse = generateResults([]); const ruleServices: RuleExecutorServicesMock = alertsMock.createRuleExecutorServices(); - (ruleServices.dataViews.create as jest.Mock).mockResolvedValueOnce({ - toSpec: () => dataViewMock.toSpec(), - }); + (ruleServices.dataViews.create as jest.Mock).mockImplementationOnce((spec: DataViewSpec) => + createStubDataView({ spec }) + ); (searchSourceInstanceMock.getField as jest.Mock).mockImplementation((name: string) => { if (name === 'index') { return dataViewMock; @@ -620,9 +621,9 @@ describe('ruleType', () => { const params = { ...defaultParams, thresholdComparator: Comparator.GT_OR_EQ, threshold: [3] }; const ruleServices: RuleExecutorServicesMock = alertsMock.createRuleExecutorServices(); - (ruleServices.dataViews.create as jest.Mock).mockResolvedValueOnce({ - toSpec: () => dataViewMock.toSpec(), - }); + (ruleServices.dataViews.create as jest.Mock).mockImplementationOnce((spec: DataViewSpec) => + createStubDataView({ spec }) + ); (searchSourceInstanceMock.getField as jest.Mock).mockImplementation((name: string) => { if (name === 'index') { return dataViewMock; From 4087316960f400124c0d11f6fa830da41649ccff Mon Sep 17 00:00:00 2001 From: Georgii Gorbachev Date: Tue, 25 Jul 2023 22:31:04 +0200 Subject: [PATCH 25/29] [Security Solution] Restructure Cypress tests under `security_solution/cypress/e2e/detection_rules` folder (#162373) **Epic:** https://github.com/elastic/kibana/issues/153633 **Partially addresses:** https://github.com/elastic/kibana/issues/153645 ## Summary This PR builds upon https://github.com/elastic/kibana/pull/161900 and moves tests located in the `e2e/detection_rules` folder into `e2e/detection_response` and splits them into multiple sub-folders according to the Detection Engine subdomains we have. It also updates the CODEOWNERS file accordingly. Screenshot 2023-07-25 at 21 03 08 ## Details Specifically, changes in this PR include: - The `e2e/detections_response` folder was renamed to `e2e/detection_response`. - The `e2e/detections_response/bulk_actions` folder became `e2e/detection_response/rule_management/rule_actions/bulk_actions`. - Cypress tests for rule types (which actually test rule creation for different rule types) were moved to `e2e/detection_response/rule_creation`. - The CODEOWNERS file was updated. Things not addressed in this PR: - No ownership was assigned for `e2e/detection_response/rule_actions`. Will need to figure this out with @yctercero. - No restructuring was done for `security_solution/cypress/screens` and `security_solution/cypress/tasks`. Will be done in follow-up PRs. - No refactoring was done for the tests themselves. Some of this work is also upcoming. The full file structure of the `detection_response` tests looks like this: Screenshot 2023-07-25 at 21 03 44 --- .github/CODEOWNERS | 18 ++++---- ...t_rules_install_update_authorization.cy.ts | 18 ++++---- ..._rules_install_update_error_handling.cy.ts | 14 +++--- ...built_rules_install_update_workflows.cy.ts | 18 ++++---- .../prebuilt_rules_management.cy.ts | 20 +++++---- .../prebuilt_rules_notifications.cy.ts | 17 +++++--- .../rule_actions}/rule_actions.cy.ts | 16 +++---- .../rule_creation}/custom_query_rule.cy.ts | 43 +++++++++++-------- .../custom_query_rule_data_view.cy.ts | 24 +++++------ .../custom_saved_query_rule.cy.ts | 26 +++++------ .../event_correlation_rule.cy.ts | 22 +++++----- .../rule_creation}/indicator_match_rule.cy.ts | 36 ++++++++-------- .../machine_learning_rule.cy.ts | 20 ++++----- .../rule_creation}/new_terms_rule.cy.ts | 22 +++++----- .../rule_creation}/override.cy.ts | 20 ++++----- .../rule_creation}/threshold_rule.cy.ts | 22 +++++----- .../authorization}/all_rules_read_only.cy.ts | 24 ++++++----- .../maintenance_window_callout.cy.ts} | 6 +-- .../related_integrations.cy.ts | 30 ++++++------- .../bulk_actions/bulk_duplicate_rules.cy.ts | 26 ++++++----- .../bulk_actions/bulk_edit_rules.cy.ts | 34 ++++++++------- .../bulk_edit_rules_actions.cy.ts | 28 ++++++------ .../bulk_edit_rules_data_view.cy.ts | 20 ++++----- .../import_export}/export_rule.cy.ts | 27 ++++++------ .../import_export}/import_rules.cy.ts | 10 ++--- .../snoozing}/rule_snoozing.cy.ts | 42 ++++++++++-------- .../rules_table_auto_refresh.cy.ts | 18 ++++---- .../rules_table/rules_table_filtering.cy.ts} | 22 ++++++---- .../rules_table/rules_table_links.cy.ts} | 14 +++--- .../rules_table_persistent_state.cy.ts} | 16 +++---- .../rules_table/rules_table_selection.cy.ts} | 16 +++---- .../rules_table/rules_table_sorting.cy.ts} | 24 ++++++----- .../value_lists/value_lists.cy.ts | 10 ++--- 33 files changed, 381 insertions(+), 342 deletions(-) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/prebuilt_rules}/prebuilt_rules_install_update_authorization.cy.ts (87%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/prebuilt_rules}/prebuilt_rules_install_update_error_handling.cy.ts (90%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/prebuilt_rules}/prebuilt_rules_install_update_workflows.cy.ts (94%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/prebuilt_rules}/prebuilt_rules_management.cy.ts (92%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/prebuilt_rules}/prebuilt_rules_notifications.cy.ts (94%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_actions}/rule_actions.cy.ts (82%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/custom_query_rule.cy.ts (93%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/custom_query_rule_data_view.cy.ts (89%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/custom_saved_query_rule.cy.ts (91%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/event_correlation_rule.cy.ts (91%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/indicator_match_rule.cy.ts (95%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/machine_learning_rule.cy.ts (88%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/new_terms_rule.cy.ts (88%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/override.cy.ts (90%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_creation}/threshold_rule.cy.ts (86%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_management/authorization}/all_rules_read_only.cy.ts (70%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules/maintenance_window.cy.ts => detection_response/rule_management/maintenance_windows/maintenance_window_callout.cy.ts} (89%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_management/related_integrations}/related_integrations.cy.ts (89%) rename x-pack/plugins/security_solution/cypress/e2e/{detections_response/rules_management => detection_response/rule_management/rule_actions}/bulk_actions/bulk_duplicate_rules.cy.ts (84%) rename x-pack/plugins/security_solution/cypress/e2e/{detections_response/rules_management => detection_response/rule_management/rule_actions}/bulk_actions/bulk_edit_rules.cy.ts (94%) rename x-pack/plugins/security_solution/cypress/e2e/{detections_response/rules_management => detection_response/rule_management/rule_actions}/bulk_actions/bulk_edit_rules_actions.cy.ts (89%) rename x-pack/plugins/security_solution/cypress/e2e/{detections_response/rules_management => detection_response/rule_management/rule_actions}/bulk_actions/bulk_edit_rules_data_view.cy.ts (93%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_management/rule_actions/import_export}/export_rule.cy.ts (87%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_management/rule_actions/import_export}/import_rules.cy.ts (88%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_management/rule_actions/snoozing}/rule_snoozing.cy.ts (84%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules => detection_response/rule_management/rules_table}/rules_table_auto_refresh.cy.ts (86%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules/rule_fiters.cy.ts => detection_response/rule_management/rules_table/rules_table_filtering.cy.ts} (82%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules/links.cy.ts => detection_response/rule_management/rules_table/rules_table_links.cy.ts} (63%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules/persistent_rules_table_state.cy.ts => detection_response/rule_management/rules_table/rules_table_persistent_state.cy.ts} (95%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules/rules_selection.cy.ts => detection_response/rule_management/rules_table/rules_table_selection.cy.ts} (86%) rename x-pack/plugins/security_solution/cypress/e2e/{detection_rules/sorting.cy.ts => detection_response/rule_management/rules_table/rules_table_sorting.cy.ts} (79%) rename x-pack/plugins/security_solution/cypress/e2e/{ => detection_response}/value_lists/value_lists.cy.ts (97%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ecca6d3ad332bf6..b316c9f4d913b28 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1114,17 +1114,19 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/plugins/stack_connectors/common/gen_ai @elastic/security-threat-hunting-explore ## Security Solution sub teams - Detection Rule Management +/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema @elastic/security-detection-rule-management @elastic/security-detection-engine /x-pack/plugins/security_solution/common/api/detection_engine/fleet_integrations @elastic/security-detection-rule-management /x-pack/plugins/security_solution/common/api/detection_engine/prebuilt_rules @elastic/security-detection-rule-management /x-pack/plugins/security_solution/common/api/detection_engine/rule_management @elastic/security-detection-rule-management /x-pack/plugins/security_solution/common/api/detection_engine/rule_monitoring @elastic/security-detection-rule-management -/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema @elastic/security-detection-rule-management @elastic/security-detection-engine - /x-pack/plugins/security_solution/common/detection_engine/fleet_integrations @elastic/security-detection-rule-management /x-pack/plugins/security_solution/common/detection_engine/prebuilt_rules @elastic/security-detection-rule-management /x-pack/plugins/security_solution/common/detection_engine/rule_management @elastic/security-detection-rule-management /x-pack/plugins/security_solution/common/detection_engine/rule_monitoring @elastic/security-detection-rule-management +/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules @elastic/security-detection-rule-management +/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management @elastic/security-detection-rule-management + /x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/prebuilt_rules @elastic/security-detection-rule-management /x-pack/plugins/security_solution/docs/testing/test_plans/detection_response/rule_management @elastic/security-detection-rule-management @@ -1145,15 +1147,12 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/plugins/security_solution/public/detections/mitre @elastic/security-detection-rule-management /x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules @elastic/security-detection-rule-management /x-pack/plugins/security_solution/public/rules @elastic/security-detection-rule-management -/x-pack/plugins/security_solution/public/entity_analytics @elastic/security-detection-engine - /x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations @elastic/security-detection-rule-management /x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules @elastic/security-detection-rule-management /x-pack/plugins/security_solution/server/lib/detection_engine/rule_management @elastic/security-detection-rule-management /x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring @elastic/security-detection-rule-management /x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema @elastic/security-detection-rule-management @elastic/security-detection-engine - /x-pack/plugins/security_solution/server/utils @elastic/security-detection-rule-management ## Security Solution sub teams - Detection Engine @@ -1163,6 +1162,7 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui @elastic/security-detection-engine /x-pack/plugins/security_solution/public/detections/pages/alerts @elastic/security-detection-engine +/x-pack/plugins/security_solution/public/entity_analytics @elastic/security-detection-engine /x-pack/plugins/security_solution/server/lib/detection_engine/migrations @elastic/security-detection-engine /x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview @elastic/security-detection-engine @@ -1171,9 +1171,11 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals @elastic/security-detection-engine /x-pack/plugins/security_solution/cypress/e2e/data_sources @elastic/security-detection-engine -/x-pack/plugins/security_solution/cypress/e2e/exceptions @elastic/security-detection-engine -/x-pack/plugins/security_solution/cypress/e2e/value_lists @elastic/security-detection-engine +/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation @elastic/security-detection-engine +/x-pack/plugins/security_solution/cypress/e2e/detection_response/value_lists @elastic/security-detection-engine /x-pack/plugins/security_solution/cypress/e2e/entity_analytics @elastic/security-detection-engine +/x-pack/plugins/security_solution/cypress/e2e/exceptions @elastic/security-detection-engine +/x-pack/plugins/security_solution/cypress/e2e/overview @elastic/security-detection-engine /x-pack/plugins/security_solution/common/detection_engine/rule_exceptions @elastic/security-detection-engine @@ -1187,8 +1189,6 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy @elastic/security-detection-engine /x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions @elastic/security-detection-engine /x-pack/plugins/security_solution/server/lib/sourcerer @elastic/security-detection-engine -/x-pack/plugins/security_solution/cypress/e2e/overview @elastic/security-detection-engine - ## Security Threat Intelligence - Under Security Platform /x-pack/plugins/security_solution/public/common/components/threat_match @elastic/security-detection-engine diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_authorization.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_authorization.cy.ts similarity index 87% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_authorization.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_authorization.cy.ts index d634d5b87e3b1cf..202fb6766fc6f7a 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_authorization.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_authorization.cy.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { APP_PATH, RULES_ADD_PATH, RULES_UPDATES } from '../../../common/constants'; -import { createRuleAssetSavedObject } from '../../helpers/rules'; -import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules'; -import { createAndInstallMockedPrebuiltRules } from '../../tasks/api_calls/prebuilt_rules'; -import { resetRulesTableState, deleteAlertsAndRules } from '../../tasks/common'; -import { login, waitForPageWithoutDateRange } from '../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; -import { ROLES } from '../../../common/test'; +import { APP_PATH, RULES_ADD_PATH, RULES_UPDATES } from '../../../../common/constants'; +import { createRuleAssetSavedObject } from '../../../helpers/rules'; +import { waitForRulesTableToBeLoaded } from '../../../tasks/alerts_detection_rules'; +import { createAndInstallMockedPrebuiltRules } from '../../../tasks/api_calls/prebuilt_rules'; +import { resetRulesTableState, deleteAlertsAndRules } from '../../../tasks/common'; +import { login, waitForPageWithoutDateRange } from '../../../tasks/login'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../urls/navigation'; +import { ROLES } from '../../../../common/test'; import { ADD_ELASTIC_RULES_BTN, getInstallSingleRuleButtonByRuleId, @@ -21,7 +21,7 @@ import { RULES_UPDATES_TAB, RULE_CHECKBOX, UPGRADE_ALL_RULES_BUTTON, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; const RULE_1_ID = 'rule_1'; const RULE_2_ID = 'rule_2'; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_error_handling.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_error_handling.cy.ts similarity index 90% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_error_handling.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_error_handling.cy.ts index ef83ea231796673..901681658961079 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_error_handling.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_error_handling.cy.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { createRuleAssetSavedObject } from '../../helpers/rules'; -import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules'; -import { createAndInstallMockedPrebuiltRules } from '../../tasks/api_calls/prebuilt_rules'; -import { resetRulesTableState, deleteAlertsAndRules, reload } from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; +import { createRuleAssetSavedObject } from '../../../helpers/rules'; +import { waitForRulesTableToBeLoaded } from '../../../tasks/alerts_detection_rules'; +import { createAndInstallMockedPrebuiltRules } from '../../../tasks/api_calls/prebuilt_rules'; +import { resetRulesTableState, deleteAlertsAndRules, reload } from '../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../urls/navigation'; import { addElasticRulesButtonClick, assertRuleAvailableForInstallAndInstallOne, @@ -22,7 +22,7 @@ import { assertRuleUpgradeAvailableAndUpgradeAllInPage, assertRuleUpgradeAvailableAndUpgradeAll, ruleUpdatesTabClick, -} from '../../tasks/prebuilt_rules'; +} from '../../../tasks/prebuilt_rules'; describe('Detection rules, Prebuilt Rules Installation and Update - Error handling', () => { beforeEach(() => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_workflows.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_workflows.cy.ts similarity index 94% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_workflows.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_workflows.cy.ts index 01d839a0bb3a399..4957d6edc3371b0 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_install_update_workflows.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_install_update_workflows.cy.ts @@ -6,8 +6,8 @@ */ import type { BulkInstallPackageInfo } from '@kbn/fleet-plugin/common'; -import type { Rule } from '../../../public/detection_engine/rule_management/logic/types'; -import { createRuleAssetSavedObject } from '../../helpers/rules'; +import type { Rule } from '../../../../public/detection_engine/rule_management/logic/types'; +import { createRuleAssetSavedObject } from '../../../helpers/rules'; import { GO_BACK_TO_RULES_TABLE_BUTTON, INSTALL_ALL_RULES_BUTTON, @@ -18,15 +18,15 @@ import { RULE_CHECKBOX, SELECT_ALL_RULES_ON_PAGE_CHECKBOX, TOASTER, -} from '../../screens/alerts_detection_rules'; -import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; +import { waitForRulesTableToBeLoaded } from '../../../tasks/alerts_detection_rules'; import { getRuleAssets, createAndInstallMockedPrebuiltRules, -} from '../../tasks/api_calls/prebuilt_rules'; -import { resetRulesTableState, deleteAlertsAndRules, reload } from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; +} from '../../../tasks/api_calls/prebuilt_rules'; +import { resetRulesTableState, deleteAlertsAndRules, reload } from '../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../urls/navigation'; import { addElasticRulesButtonClick, assertRuleAvailableForInstallAndInstallOne, @@ -38,7 +38,7 @@ import { assertRuleUpgradeAvailableAndUpgradeAllInPage, assertRuleUpgradeAvailableAndUpgradeAll, ruleUpdatesTabClick, -} from '../../tasks/prebuilt_rules'; +} from '../../../tasks/prebuilt_rules'; describe('Detection rules, Prebuilt Rules Installation and Update workflow', () => { beforeEach(() => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_management.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_management.cy.ts similarity index 92% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_management.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_management.cy.ts index eea13a4def02b30..b24f62704fe46c6 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_management.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_management.cy.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { createRuleAssetSavedObject } from '../../helpers/rules'; +import { createRuleAssetSavedObject } from '../../../helpers/rules'; import { COLLAPSED_ACTION_BTN, ELASTIC_RULES_BTN, @@ -17,7 +17,7 @@ import { RULE_SWITCH, SELECT_ALL_RULES_ON_PAGE_CHECKBOX, INSTALL_ALL_RULES_BUTTON, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { confirmRulesDelete, deleteFirstRule, @@ -25,19 +25,23 @@ import { selectNumberOfRules, waitForPrebuiltDetectionRulesToBeLoaded, waitForRuleToUpdate, -} from '../../tasks/alerts_detection_rules'; +} from '../../../tasks/alerts_detection_rules'; import { deleteSelectedRules, disableSelectedRules, enableSelectedRules, -} from '../../tasks/rules_bulk_actions'; +} from '../../../tasks/rules_bulk_actions'; import { createAndInstallMockedPrebuiltRules, getAvailablePrebuiltRulesCount, -} from '../../tasks/api_calls/prebuilt_rules'; -import { cleanKibana, deleteAlertsAndRules, deletePrebuiltRulesAssets } from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +} from '../../../tasks/api_calls/prebuilt_rules'; +import { + cleanKibana, + deleteAlertsAndRules, + deletePrebuiltRulesAssets, +} from '../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; const rules = Array.from(Array(5)).map((_, i) => { return createRuleAssetSavedObject({ diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_notifications.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_notifications.cy.ts similarity index 94% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_notifications.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_notifications.cy.ts index 9648d565e5f7386..9fb1dcf16cbfe61 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules_notifications.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/prebuilt_rules/prebuilt_rules_notifications.cy.ts @@ -5,21 +5,24 @@ * 2.0. */ -import { createRuleAssetSavedObject } from '../../helpers/rules'; -import { ADD_ELASTIC_RULES_BTN, RULES_UPDATES_TAB } from '../../screens/alerts_detection_rules'; -import { deleteFirstRule, waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules'; +import { createRuleAssetSavedObject } from '../../../helpers/rules'; +import { ADD_ELASTIC_RULES_BTN, RULES_UPDATES_TAB } from '../../../screens/alerts_detection_rules'; +import { + deleteFirstRule, + waitForRulesTableToBeLoaded, +} from '../../../tasks/alerts_detection_rules'; import { installAllPrebuiltRulesRequest, createAndInstallMockedPrebuiltRules, -} from '../../tasks/api_calls/prebuilt_rules'; +} from '../../../tasks/api_calls/prebuilt_rules'; import { resetRulesTableState, deleteAlertsAndRules, reload, deletePrebuiltRulesAssets, -} from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; +} from '../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../urls/navigation'; const RULE_1 = createRuleAssetSavedObject({ name: 'Test rule 1', diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_actions.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_actions/rule_actions.cy.ts similarity index 82% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_actions.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_actions/rule_actions.cy.ts index 04ff3adb7865590..58bf0726918c099 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_actions.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_actions/rule_actions.cy.ts @@ -5,27 +5,27 @@ * 2.0. */ -import { getIndexConnector } from '../../objects/connector'; -import { getSimpleCustomQueryRule } from '../../objects/rule'; +import { getIndexConnector } from '../../../objects/connector'; +import { getSimpleCustomQueryRule } from '../../../objects/rule'; -import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; -import { deleteIndex, waitForNewDocumentToBeIndexed } from '../../tasks/api_calls/elasticsearch'; +import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { deleteIndex, waitForNewDocumentToBeIndexed } from '../../../tasks/api_calls/elasticsearch'; import { cleanKibana, deleteAlertsAndRules, deleteConnectors, deleteDataView, -} from '../../tasks/common'; +} from '../../../tasks/common'; import { createAndEnableRule, fillAboutRuleAndContinue, fillDefineCustomRuleAndContinue, fillRuleAction, fillScheduleRuleAndContinue, -} from '../../tasks/create_new_rule'; -import { login, visit } from '../../tasks/login'; +} from '../../../tasks/create_new_rule'; +import { login, visit } from '../../../tasks/login'; -import { RULE_CREATION } from '../../urls/navigation'; +import { RULE_CREATION } from '../../../urls/navigation'; describe('Rule actions during detection rule creation', () => { const indexConnector = getIndexConnector(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_query_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_query_rule.cy.ts similarity index 93% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_query_rule.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_query_rule.cy.ts index d6eb89cee13d8cd..eb1abd71cd43e2c 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_query_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_query_rule.cy.ts @@ -5,10 +5,15 @@ * 2.0. */ -import { ruleFields } from '../../data/detection_engine'; -import { getNewRule, getExistingRule, getEditedRule, getNewOverrideRule } from '../../objects/rule'; -import { getTimeline } from '../../objects/timeline'; -import { ALERTS_COUNT, ALERT_GRID_CELL } from '../../screens/alerts'; +import { ruleFields } from '../../../data/detection_engine'; +import { + getNewRule, + getExistingRule, + getEditedRule, + getNewOverrideRule, +} from '../../../objects/rule'; +import { getTimeline } from '../../../objects/timeline'; +import { ALERTS_COUNT, ALERT_GRID_CELL } from '../../../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -18,11 +23,11 @@ import { RULES_MANAGEMENT_TABLE, RULE_SWITCH, SEVERITY, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { ACTIONS_NOTIFY_WHEN_BUTTON, ACTIONS_SUMMARY_BUTTON, -} from '../../screens/common/rule_actions'; +} from '../../../screens/common/rule_actions'; import { ABOUT_CONTINUE_BTN, ABOUT_EDIT_BUTTON, @@ -39,7 +44,7 @@ import { SEVERITY_DROPDOWN, TAGS_CLEAR_BUTTON, TAGS_FIELD, -} from '../../screens/create_new_rule'; +} from '../../../screens/create_new_rule'; import { ADDITIONAL_LOOK_BACK_DETAILS, ABOUT_DETAILS, @@ -64,7 +69,7 @@ import { THREAT_TACTIC, THREAT_TECHNIQUE, THREAT_SUBTECHNIQUE, -} from '../../screens/rule_details'; +} from '../../../screens/rule_details'; import { deleteFirstRule, @@ -72,12 +77,12 @@ import { editFirstRule, goToRuleDetails, selectNumberOfRules, -} from '../../tasks/alerts_detection_rules'; -import { deleteSelectedRules } from '../../tasks/rules_bulk_actions'; -import { createRule } from '../../tasks/api_calls/rules'; -import { createTimeline } from '../../tasks/api_calls/timelines'; -import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../tasks/common'; -import { addEmailConnectorAndRuleAction } from '../../tasks/common/rule_actions'; +} from '../../../tasks/alerts_detection_rules'; +import { deleteSelectedRules } from '../../../tasks/rules_bulk_actions'; +import { createRule } from '../../../tasks/api_calls/rules'; +import { createTimeline } from '../../../tasks/api_calls/timelines'; +import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../../tasks/common'; +import { addEmailConnectorAndRuleAction } from '../../../tasks/common/rule_actions'; import { createAndEnableRule, expandAdvancedSettings, @@ -100,12 +105,12 @@ import { importSavedQuery, waitForAlertsToPopulate, waitForTheRuleToBeExecuted, -} from '../../tasks/create_new_rule'; -import { saveEditedRule } from '../../tasks/edit_rule'; -import { login, visit } from '../../tasks/login'; -import { enablesRule, getDetails } from '../../tasks/rule_details'; +} from '../../../tasks/create_new_rule'; +import { saveEditedRule } from '../../../tasks/edit_rule'; +import { login, visit } from '../../../tasks/login'; +import { enablesRule, getDetails } from '../../../tasks/rule_details'; -import { RULE_CREATION, DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { RULE_CREATION, DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; describe('Custom query rules', () => { before(() => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_query_rule_data_view.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_query_rule_data_view.cy.ts similarity index 89% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_query_rule_data_view.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_query_rule_data_view.cy.ts index 3298cbb32adcc39..b1bcf1336670a67 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_query_rule_data_view.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_query_rule_data_view.cy.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { formatMitreAttackDescription, getHumanizedDuration } from '../../helpers/rules'; -import { getDataViewRule } from '../../objects/rule'; -import { ALERTS_COUNT, ALERT_GRID_CELL } from '../../screens/alerts'; +import { formatMitreAttackDescription, getHumanizedDuration } from '../../../helpers/rules'; +import { getDataViewRule } from '../../../objects/rule'; +import { ALERTS_COUNT, ALERT_GRID_CELL } from '../../../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -17,12 +17,12 @@ import { RULES_MANAGEMENT_TABLE, RULE_SWITCH, SEVERITY, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { ABOUT_CONTINUE_BTN, RULE_DESCRIPTION_INPUT, RULE_NAME_INPUT, -} from '../../screens/create_new_rule'; +} from '../../../screens/create_new_rule'; import { ADDITIONAL_LOOK_BACK_DETAILS, @@ -48,10 +48,10 @@ import { TIMELINE_TEMPLATE_DETAILS, DATA_VIEW_DETAILS, EDIT_RULE_SETTINGS_LINK, -} from '../../screens/rule_details'; +} from '../../../screens/rule_details'; -import { goToRuleDetails } from '../../tasks/alerts_detection_rules'; -import { postDataView } from '../../tasks/common'; +import { goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { postDataView } from '../../../tasks/common'; import { createAndEnableRule, createRuleWithoutEnabling, @@ -60,12 +60,12 @@ import { fillScheduleRuleAndContinue, waitForAlertsToPopulate, waitForTheRuleToBeExecuted, -} from '../../tasks/create_new_rule'; +} from '../../../tasks/create_new_rule'; -import { login, visit } from '../../tasks/login'; -import { getDetails } from '../../tasks/rule_details'; +import { login, visit } from '../../../tasks/login'; +import { getDetails } from '../../../tasks/rule_details'; -import { RULE_CREATION } from '../../urls/navigation'; +import { RULE_CREATION } from '../../../urls/navigation'; describe('Custom query rules', () => { describe('Custom detection rules creation with data views', () => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_saved_query_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_saved_query_rule.cy.ts similarity index 91% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_saved_query_rule.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_saved_query_rule.cy.ts index 3d5d0ec7252698d..3c43bca29260220 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_saved_query_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/custom_saved_query_rule.cy.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { getNewRule, getSavedQueryRule } from '../../objects/rule'; +import { getNewRule, getSavedQueryRule } from '../../../objects/rule'; import { DEFINE_CONTINUE_BUTTON, CUSTOM_QUERY_BAR, LOAD_QUERY_DYNAMICALLY_CHECKBOX, QUERY_BAR, -} from '../../screens/create_new_rule'; -import { TOASTER } from '../../screens/alerts_detection_rules'; +} from '../../../screens/create_new_rule'; +import { TOASTER } from '../../../screens/alerts_detection_rules'; import { RULE_NAME_HEADER, SAVED_QUERY_NAME_DETAILS, @@ -21,11 +21,11 @@ import { SAVED_QUERY_FILTERS_DETAILS, DEFINE_RULE_PANEL_PROGRESS, CUSTOM_QUERY_DETAILS, -} from '../../screens/rule_details'; +} from '../../../screens/rule_details'; -import { goToRuleDetails, editFirstRule } from '../../tasks/alerts_detection_rules'; -import { createSavedQuery, deleteSavedQueries } from '../../tasks/api_calls/saved_queries'; -import { cleanKibana, deleteAlertsAndRules } from '../../tasks/common'; +import { goToRuleDetails, editFirstRule } from '../../../tasks/alerts_detection_rules'; +import { createSavedQuery, deleteSavedQueries } from '../../../tasks/api_calls/saved_queries'; +import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { createAndEnableRule, fillAboutRuleAndContinue, @@ -34,13 +34,13 @@ import { getCustomQueryInput, checkLoadQueryDynamically, uncheckLoadQueryDynamically, -} from '../../tasks/create_new_rule'; -import { saveEditedRule } from '../../tasks/edit_rule'; -import { login, visit } from '../../tasks/login'; -import { getDetails } from '../../tasks/rule_details'; -import { createRule } from '../../tasks/api_calls/rules'; +} from '../../../tasks/create_new_rule'; +import { saveEditedRule } from '../../../tasks/edit_rule'; +import { login, visit } from '../../../tasks/login'; +import { getDetails } from '../../../tasks/rule_details'; +import { createRule } from '../../../tasks/api_calls/rules'; -import { RULE_CREATION, SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; +import { RULE_CREATION, SECURITY_DETECTIONS_RULES_URL } from '../../../urls/navigation'; const savedQueryName = 'custom saved query'; const savedQueryQuery = 'process.name: test'; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/event_correlation_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts similarity index 91% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/event_correlation_rule.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts index bc7d9c2bea863bc..a470a322b18316e 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/event_correlation_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/event_correlation_rule.cy.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { formatMitreAttackDescription, getHumanizedDuration } from '../../helpers/rules'; -import { getEqlRule, getEqlSequenceRule, getIndexPatterns } from '../../objects/rule'; +import { formatMitreAttackDescription, getHumanizedDuration } from '../../../helpers/rules'; +import { getEqlRule, getEqlSequenceRule, getIndexPatterns } from '../../../objects/rule'; -import { ALERTS_COUNT, ALERT_DATA_GRID } from '../../screens/alerts'; +import { ALERTS_COUNT, ALERT_DATA_GRID } from '../../../screens/alerts'; import { CUSTOM_RULES_BTN, RISK_SCORE, @@ -16,7 +16,7 @@ import { RULE_NAME, RULE_SWITCH, SEVERITY, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { ABOUT_DETAILS, ABOUT_INVESTIGATION_NOTES, @@ -39,15 +39,15 @@ import { SEVERITY_DETAILS, TAGS_DETAILS, TIMELINE_TEMPLATE_DETAILS, -} from '../../screens/rule_details'; +} from '../../../screens/rule_details'; -import { getDetails } from '../../tasks/rule_details'; +import { getDetails } from '../../../tasks/rule_details'; import { expectNumberOfRules, goToRuleDetails, goToTheRuleDetailsOf, -} from '../../tasks/alerts_detection_rules'; -import { cleanKibana, deleteAlertsAndRules } from '../../tasks/common'; +} from '../../../tasks/alerts_detection_rules'; +import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { createAndEnableRule, fillAboutRuleAndContinue, @@ -56,10 +56,10 @@ import { selectEqlRuleType, waitForAlertsToPopulate, waitForTheRuleToBeExecuted, -} from '../../tasks/create_new_rule'; -import { login, visit } from '../../tasks/login'; +} from '../../../tasks/create_new_rule'; +import { login, visit } from '../../../tasks/login'; -import { RULE_CREATION } from '../../urls/navigation'; +import { RULE_CREATION } from '../../../urls/navigation'; describe('EQL rules', () => { before(() => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts similarity index 95% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts index f7b5ed197f43fdf..ec216364a203142 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/indicator_match_rule.cy.ts @@ -5,20 +5,20 @@ * 2.0. */ -import { formatMitreAttackDescription, getHumanizedDuration } from '../../helpers/rules'; +import { formatMitreAttackDescription, getHumanizedDuration } from '../../../helpers/rules'; import { getIndexPatterns, getNewThreatIndicatorRule, getThreatIndexPatterns, indicatorRuleMatchingDoc, -} from '../../objects/rule'; +} from '../../../objects/rule'; import { ALERT_RULE_NAME, ALERT_RISK_SCORE, ALERT_SEVERITY, ALERTS_COUNT, -} from '../../screens/alerts'; +} from '../../../screens/alerts'; import { CUSTOM_RULES_BTN, RISK_SCORE, @@ -26,7 +26,7 @@ import { RULE_NAME, RULE_SWITCH, SEVERITY, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { ABOUT_DETAILS, ABOUT_INVESTIGATION_NOTES, @@ -53,9 +53,9 @@ import { SEVERITY_DETAILS, TAGS_DETAILS, TIMELINE_TEMPLATE_DETAILS, -} from '../../screens/rule_details'; -import { INDICATOR_MATCH_ROW_RENDER, PROVIDER_BADGE } from '../../screens/timeline'; -import { investigateFirstAlertInTimeline } from '../../tasks/alerts'; +} from '../../../screens/rule_details'; +import { INDICATOR_MATCH_ROW_RENDER, PROVIDER_BADGE } from '../../../screens/timeline'; +import { investigateFirstAlertInTimeline } from '../../../tasks/alerts'; import { duplicateFirstRule, duplicateRuleFromMenu, @@ -63,11 +63,11 @@ import { selectNumberOfRules, checkDuplicatedRule, expectNumberOfRules, -} from '../../tasks/alerts_detection_rules'; -import { duplicateSelectedRulesWithExceptions } from '../../tasks/rules_bulk_actions'; -import { createRule } from '../../tasks/api_calls/rules'; -import { loadPrepackagedTimelineTemplates } from '../../tasks/api_calls/timelines'; -import { cleanKibana, deleteAlertsAndRules } from '../../tasks/common'; +} from '../../../tasks/alerts_detection_rules'; +import { duplicateSelectedRulesWithExceptions } from '../../../tasks/rules_bulk_actions'; +import { createRule } from '../../../tasks/api_calls/rules'; +import { loadPrepackagedTimelineTemplates } from '../../../tasks/api_calls/timelines'; +import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { createAndEnableRule, fillAboutRuleAndContinue, @@ -93,18 +93,18 @@ import { selectIndicatorMatchType, waitForAlertsToPopulate, waitForTheRuleToBeExecuted, -} from '../../tasks/create_new_rule'; +} from '../../../tasks/create_new_rule'; import { SCHEDULE_INTERVAL_AMOUNT_INPUT, SCHEDULE_INTERVAL_UNITS_INPUT, SCHEDULE_LOOKBACK_AMOUNT_INPUT, SCHEDULE_LOOKBACK_UNITS_INPUT, -} from '../../screens/create_new_rule'; -import { goBackToRuleDetails } from '../../tasks/edit_rule'; -import { login, visit, visitWithoutDateRange } from '../../tasks/login'; -import { goBackToRulesTable, getDetails } from '../../tasks/rule_details'; +} from '../../../screens/create_new_rule'; +import { goBackToRuleDetails } from '../../../tasks/edit_rule'; +import { login, visit, visitWithoutDateRange } from '../../../tasks/login'; +import { goBackToRulesTable, getDetails } from '../../../tasks/rule_details'; -import { DETECTIONS_RULE_MANAGEMENT_URL, RULE_CREATION } from '../../urls/navigation'; +import { DETECTIONS_RULE_MANAGEMENT_URL, RULE_CREATION } from '../../../urls/navigation'; const DEFAULT_THREAT_MATCH_QUERY = '@timestamp >= "now-30d/d"'; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/machine_learning_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/machine_learning_rule.cy.ts similarity index 88% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/machine_learning_rule.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/machine_learning_rule.cy.ts index 6c5de4f505af81d..d975be9249a5e53 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/machine_learning_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/machine_learning_rule.cy.ts @@ -7,8 +7,8 @@ import { isArray } from 'lodash'; -import { formatMitreAttackDescription, getHumanizedDuration } from '../../helpers/rules'; -import { getMachineLearningRule } from '../../objects/rule'; +import { formatMitreAttackDescription, getHumanizedDuration } from '../../../helpers/rules'; +import { getMachineLearningRule } from '../../../objects/rule'; import { CUSTOM_RULES_BTN, @@ -17,7 +17,7 @@ import { RULE_NAME, RULE_SWITCH, SEVERITY, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { ABOUT_DETAILS, ABOUT_RULE_DESCRIPTION, @@ -38,21 +38,21 @@ import { SEVERITY_DETAILS, TAGS_DETAILS, TIMELINE_TEMPLATE_DETAILS, -} from '../../screens/rule_details'; +} from '../../../screens/rule_details'; -import { getDetails } from '../../tasks/rule_details'; -import { expectNumberOfRules, goToRuleDetails } from '../../tasks/alerts_detection_rules'; -import { cleanKibana } from '../../tasks/common'; +import { getDetails } from '../../../tasks/rule_details'; +import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { cleanKibana } from '../../../tasks/common'; import { createAndEnableRule, fillAboutRuleAndContinue, fillDefineMachineLearningRuleAndContinue, fillScheduleRuleAndContinue, selectMachineLearningRuleType, -} from '../../tasks/create_new_rule'; -import { login, visitWithoutDateRange } from '../../tasks/login'; +} from '../../../tasks/create_new_rule'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; -import { RULE_CREATION } from '../../urls/navigation'; +import { RULE_CREATION } from '../../../urls/navigation'; describe('Detection rules, machine learning', () => { const expectedUrls = (getMachineLearningRule().references ?? []).join(''); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/new_terms_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/new_terms_rule.cy.ts similarity index 88% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/new_terms_rule.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/new_terms_rule.cy.ts index 7e46d5d67f6db4b..ae6296aea904bd0 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/new_terms_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/new_terms_rule.cy.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { formatMitreAttackDescription, getHumanizedDuration } from '../../helpers/rules'; -import { getIndexPatterns, getNewTermsRule } from '../../objects/rule'; +import { formatMitreAttackDescription, getHumanizedDuration } from '../../../helpers/rules'; +import { getIndexPatterns, getNewTermsRule } from '../../../objects/rule'; -import { ALERT_DATA_GRID } from '../../screens/alerts'; +import { ALERT_DATA_GRID } from '../../../screens/alerts'; import { CUSTOM_RULES_BTN, RISK_SCORE, @@ -16,7 +16,7 @@ import { RULE_NAME, RULE_SWITCH, SEVERITY, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { ABOUT_DETAILS, ABOUT_INVESTIGATION_NOTES, @@ -41,11 +41,11 @@ import { TIMELINE_TEMPLATE_DETAILS, NEW_TERMS_HISTORY_WINDOW_DETAILS, NEW_TERMS_FIELDS_DETAILS, -} from '../../screens/rule_details'; +} from '../../../screens/rule_details'; -import { getDetails } from '../../tasks/rule_details'; -import { expectNumberOfRules, goToRuleDetails } from '../../tasks/alerts_detection_rules'; -import { cleanKibana, deleteAlertsAndRules } from '../../tasks/common'; +import { getDetails } from '../../../tasks/rule_details'; +import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { createAndEnableRule, fillAboutRuleAndContinue, @@ -54,10 +54,10 @@ import { selectNewTermsRuleType, waitForAlertsToPopulate, waitForTheRuleToBeExecuted, -} from '../../tasks/create_new_rule'; -import { login, visit } from '../../tasks/login'; +} from '../../../tasks/create_new_rule'; +import { login, visit } from '../../../tasks/login'; -import { RULE_CREATION } from '../../urls/navigation'; +import { RULE_CREATION } from '../../../urls/navigation'; describe('New Terms rules', () => { before(() => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/override.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/override.cy.ts similarity index 90% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/override.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/override.cy.ts index 3e8f7b22f46652e..0e6a9462237d8d6 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/override.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/override.cy.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { formatMitreAttackDescription, getHumanizedDuration } from '../../helpers/rules'; -import { getIndexPatterns, getNewOverrideRule, getSeveritiesOverride } from '../../objects/rule'; +import { formatMitreAttackDescription, getHumanizedDuration } from '../../../helpers/rules'; +import { getIndexPatterns, getNewOverrideRule, getSeveritiesOverride } from '../../../objects/rule'; -import { ALERT_GRID_CELL, ALERTS_COUNT } from '../../screens/alerts'; +import { ALERT_GRID_CELL, ALERTS_COUNT } from '../../../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -17,7 +17,7 @@ import { RULE_NAME, RULE_SWITCH, SEVERITY, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { ABOUT_INVESTIGATION_NOTES, ABOUT_DETAILS, @@ -45,9 +45,9 @@ import { TAGS_DETAILS, TIMELINE_TEMPLATE_DETAILS, TIMESTAMP_OVERRIDE_DETAILS, -} from '../../screens/rule_details'; +} from '../../../screens/rule_details'; -import { expectNumberOfRules, goToRuleDetails } from '../../tasks/alerts_detection_rules'; +import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; import { createAndEnableRule, fillAboutRuleWithOverrideAndContinue, @@ -55,11 +55,11 @@ import { fillScheduleRuleAndContinue, waitForAlertsToPopulate, waitForTheRuleToBeExecuted, -} from '../../tasks/create_new_rule'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { getDetails } from '../../tasks/rule_details'; +} from '../../../tasks/create_new_rule'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; +import { getDetails } from '../../../tasks/rule_details'; -import { RULE_CREATION } from '../../urls/navigation'; +import { RULE_CREATION } from '../../../urls/navigation'; describe('Detection rules, override', () => { const rule = getNewOverrideRule(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/threshold_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts similarity index 86% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/threshold_rule.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts index e7f96ded0b06e03..5c244b8bb52cab4 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/threshold_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_creation/threshold_rule.cy.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { formatMitreAttackDescription, getHumanizedDuration } from '../../helpers/rules'; -import { getIndexPatterns, getNewThresholdRule } from '../../objects/rule'; +import { formatMitreAttackDescription, getHumanizedDuration } from '../../../helpers/rules'; +import { getIndexPatterns, getNewThresholdRule } from '../../../objects/rule'; -import { ALERTS_COUNT, ALERT_GRID_CELL } from '../../screens/alerts'; +import { ALERTS_COUNT, ALERT_GRID_CELL } from '../../../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -17,7 +17,7 @@ import { RULE_NAME, RULE_SWITCH, SEVERITY, -} from '../../screens/alerts_detection_rules'; +} from '../../../screens/alerts_detection_rules'; import { ABOUT_DETAILS, ABOUT_INVESTIGATION_NOTES, @@ -41,11 +41,11 @@ import { TAGS_DETAILS, THRESHOLD_DETAILS, TIMELINE_TEMPLATE_DETAILS, -} from '../../screens/rule_details'; +} from '../../../screens/rule_details'; -import { getDetails } from '../../tasks/rule_details'; -import { expectNumberOfRules, goToRuleDetails } from '../../tasks/alerts_detection_rules'; -import { cleanKibana, deleteAlertsAndRules } from '../../tasks/common'; +import { getDetails } from '../../../tasks/rule_details'; +import { expectNumberOfRules, goToRuleDetails } from '../../../tasks/alerts_detection_rules'; +import { cleanKibana, deleteAlertsAndRules } from '../../../tasks/common'; import { createAndEnableRule, fillAboutRuleAndContinue, @@ -54,10 +54,10 @@ import { selectThresholdRuleType, waitForAlertsToPopulate, waitForTheRuleToBeExecuted, -} from '../../tasks/create_new_rule'; -import { login, visitWithoutDateRange } from '../../tasks/login'; +} from '../../../tasks/create_new_rule'; +import { login, visitWithoutDateRange } from '../../../tasks/login'; -import { RULE_CREATION } from '../../urls/navigation'; +import { RULE_CREATION } from '../../../urls/navigation'; describe('Detection rules, threshold', () => { const rule = getNewThresholdRule(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/all_rules_read_only.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/authorization/all_rules_read_only.cy.ts similarity index 70% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/all_rules_read_only.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/authorization/all_rules_read_only.cy.ts index 254990f73cb0ed9..eb7fa7054896f21 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/all_rules_read_only.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/authorization/all_rules_read_only.cy.ts @@ -5,20 +5,24 @@ * 2.0. */ -import { ROLES } from '../../../common/test'; -import { getNewRule } from '../../objects/rule'; +import { ROLES } from '../../../../../common/test'; +import { getNewRule } from '../../../../objects/rule'; import { COLLAPSED_ACTION_BTN, RULE_CHECKBOX, RULE_NAME, -} from '../../screens/alerts_detection_rules'; -import { VALUE_LISTS_MODAL_ACTIVATOR } from '../../screens/lists'; -import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules'; -import { createRule } from '../../tasks/api_calls/rules'; -import { cleanKibana } from '../../tasks/common'; -import { dismissCallOut, getCallOut, waitForCallOutToBeShown } from '../../tasks/common/callouts'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; +} from '../../../../screens/alerts_detection_rules'; +import { VALUE_LISTS_MODAL_ACTIVATOR } from '../../../../screens/lists'; +import { waitForRulesTableToBeLoaded } from '../../../../tasks/alerts_detection_rules'; +import { createRule } from '../../../../tasks/api_calls/rules'; +import { cleanKibana } from '../../../../tasks/common'; +import { + dismissCallOut, + getCallOut, + waitForCallOutToBeShown, +} from '../../../../tasks/common/callouts'; +import { login, visitWithoutDateRange } from '../../../../tasks/login'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../../urls/navigation'; const MISSING_PRIVILEGES_CALLOUT = 'missing-user-privileges'; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/maintenance_window.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/maintenance_windows/maintenance_window_callout.cy.ts similarity index 89% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/maintenance_window.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/maintenance_windows/maintenance_window_callout.cy.ts index bdd481762c29b7d..738c844262bf21d 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/maintenance_window.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/maintenance_windows/maintenance_window_callout.cy.ts @@ -8,9 +8,9 @@ import { INTERNAL_ALERTING_API_MAINTENANCE_WINDOW_PATH } from '@kbn/alerting-plugin/common'; import type { MaintenanceWindowCreateBody } from '@kbn/alerting-plugin/common'; import type { AsApiContract } from '@kbn/alerting-plugin/server/routes/lib'; -import { cleanKibana } from '../../tasks/common'; -import { login, visit } from '../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { cleanKibana } from '../../../../tasks/common'; +import { login, visit } from '../../../../tasks/login'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; describe('Maintenance window callout on Rule Management page', () => { let maintenanceWindowId = ''; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/related_integrations/related_integrations.cy.ts similarity index 89% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/related_integrations/related_integrations.cy.ts index 8f787a3826396e0..56865abd794c321 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/related_integrations/related_integrations.cy.ts @@ -5,36 +5,36 @@ * 2.0. */ -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; -import { FIELD } from '../../screens/alerts_details'; -import { INTEGRATIONS, INTEGRATIONS_STATUS } from '../../screens/rule_details'; +import { FIELD } from '../../../../screens/alerts_details'; +import { INTEGRATIONS, INTEGRATIONS_STATUS } from '../../../../screens/rule_details'; import { INTEGRATIONS_POPOVER, INTEGRATIONS_POPOVER_TITLE, RULE_NAME, -} from '../../screens/alerts_detection_rules'; +} from '../../../../screens/alerts_detection_rules'; -import { cleanFleet } from '../../tasks/api_calls/fleet'; -import { importRule } from '../../tasks/api_calls/rules'; +import { cleanFleet } from '../../../../tasks/api_calls/fleet'; +import { importRule } from '../../../../tasks/api_calls/rules'; import { disableRelatedIntegrations, enableRelatedIntegrations, -} from '../../tasks/api_calls/kibana_advanced_settings'; - -import { cleanKibana } from '../../tasks/common'; -import { login, visit } from '../../tasks/login'; -import { expandFirstAlert } from '../../tasks/alerts'; -import { filterBy, openTable } from '../../tasks/alerts_details'; -import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; -import { installAwsCloudFrontWithPolicy } from '../../tasks/integrations'; +} from '../../../../tasks/api_calls/kibana_advanced_settings'; + +import { cleanKibana } from '../../../../tasks/common'; +import { login, visit } from '../../../../tasks/login'; +import { expandFirstAlert } from '../../../../tasks/alerts'; +import { filterBy, openTable } from '../../../../tasks/alerts_details'; +import { waitForAlertsToPopulate } from '../../../../tasks/create_new_rule'; +import { installAwsCloudFrontWithPolicy } from '../../../../tasks/integrations'; import { enableRule, goToTheRuleDetailsOf, openIntegrationsPopover, waitForRulesTableToShow, waitForRuleToUpdate, -} from '../../tasks/alerts_detection_rules'; +} from '../../../../tasks/alerts_detection_rules'; /* Note that the rule we are using for testing purposes has the following characteristics, changing that may affect the coverage. diff --git a/x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_duplicate_rules.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_duplicate_rules.cy.ts similarity index 84% rename from x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_duplicate_rules.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_duplicate_rules.cy.ts index 2f091fd4d03afe0..c687deff53cf9f0 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_duplicate_rules.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_duplicate_rules.cy.ts @@ -10,27 +10,31 @@ import { goToTheRuleDetailsOf, selectNumberOfRules, expectManagementTableRules, -} from '../../../../tasks/alerts_detection_rules'; +} from '../../../../../tasks/alerts_detection_rules'; import { duplicateSelectedRulesWithoutExceptions, duplicateSelectedRulesWithExceptions, duplicateSelectedRulesWithNonExpiredExceptions, -} from '../../../../tasks/rules_bulk_actions'; -import { goToExceptionsTab, viewExpiredExceptionItems } from '../../../../tasks/rule_details'; -import { login, visitWithoutDateRange } from '../../../../tasks/login'; +} from '../../../../../tasks/rules_bulk_actions'; +import { goToExceptionsTab, viewExpiredExceptionItems } from '../../../../../tasks/rule_details'; +import { login, visitWithoutDateRange } from '../../../../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../../../urls/navigation'; -import { createRule } from '../../../../tasks/api_calls/rules'; -import { cleanKibana, resetRulesTableState, deleteAlertsAndRules } from '../../../../tasks/common'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../../../urls/navigation'; +import { createRule } from '../../../../../tasks/api_calls/rules'; +import { + cleanKibana, + resetRulesTableState, + deleteAlertsAndRules, +} from '../../../../../tasks/common'; -import { getNewRule } from '../../../../objects/rule'; +import { getNewRule } from '../../../../../objects/rule'; -import { createRuleExceptionItem } from '../../../../tasks/api_calls/exceptions'; -import { EXCEPTION_CARD_ITEM_NAME } from '../../../../screens/exceptions'; +import { createRuleExceptionItem } from '../../../../../tasks/api_calls/exceptions'; +import { EXCEPTION_CARD_ITEM_NAME } from '../../../../../screens/exceptions'; import { assertExceptionItemsExists, assertNumberOfExceptionItemsExists, -} from '../../../../tasks/exceptions'; +} from '../../../../../tasks/exceptions'; const RULE_NAME = 'Custom rule for bulk actions'; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts similarity index 94% rename from x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts index efb546fb8ec29bf..385a4476b2e8a20 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules.cy.ts @@ -11,7 +11,7 @@ import { RULE_CHECKBOX, RULES_TAGS_POPOVER_BTN, MODAL_ERROR_BODY, -} from '../../../../screens/alerts_detection_rules'; +} from '../../../../../screens/alerts_detection_rules'; import { RULES_BULK_EDIT_INDEX_PATTERNS_WARNING, @@ -20,11 +20,11 @@ import { TAGS_RULE_BULK_MENU_ITEM, INDEX_PATTERNS_RULE_BULK_MENU_ITEM, APPLY_TIMELINE_RULE_BULK_MENU_ITEM, -} from '../../../../screens/rules_bulk_actions'; +} from '../../../../../screens/rules_bulk_actions'; -import { TIMELINE_TEMPLATE_DETAILS } from '../../../../screens/rule_details'; +import { TIMELINE_TEMPLATE_DETAILS } from '../../../../../screens/rule_details'; -import { EUI_FILTER_SELECT_ITEM } from '../../../../screens/common/controls'; +import { EUI_FILTER_SELECT_ITEM } from '../../../../../screens/common/controls'; import { waitForRulesTableToBeLoaded, @@ -38,7 +38,7 @@ import { clickErrorToastBtn, unselectRuleByName, cancelConfirmationModal, -} from '../../../../tasks/alerts_detection_rules'; +} from '../../../../../tasks/alerts_detection_rules'; import { typeIndexPatterns, @@ -69,15 +69,19 @@ import { assertRuleScheduleValues, assertUpdateScheduleWarningExists, assertDefaultValuesAreAppliedToScheduleFields, -} from '../../../../tasks/rules_bulk_actions'; +} from '../../../../../tasks/rules_bulk_actions'; -import { hasIndexPatterns, getDetails } from '../../../../tasks/rule_details'; -import { login, visitWithoutDateRange } from '../../../../tasks/login'; +import { hasIndexPatterns, getDetails } from '../../../../../tasks/rule_details'; +import { login, visitWithoutDateRange } from '../../../../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../../../urls/navigation'; -import { createRule } from '../../../../tasks/api_calls/rules'; -import { loadPrepackagedTimelineTemplates } from '../../../../tasks/api_calls/timelines'; -import { cleanKibana, resetRulesTableState, deleteAlertsAndRules } from '../../../../tasks/common'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../../../urls/navigation'; +import { createRule } from '../../../../../tasks/api_calls/rules'; +import { loadPrepackagedTimelineTemplates } from '../../../../../tasks/api_calls/timelines'; +import { + cleanKibana, + resetRulesTableState, + deleteAlertsAndRules, +} from '../../../../../tasks/common'; import { getEqlRule, @@ -86,13 +90,13 @@ import { getNewThresholdRule, getMachineLearningRule, getNewTermsRule, -} from '../../../../objects/rule'; +} from '../../../../../objects/rule'; import { getAvailablePrebuiltRulesCount, excessivelyInstallAllPrebuiltRules, -} from '../../../../tasks/api_calls/prebuilt_rules'; -import { setRowsPerPageTo } from '../../../../tasks/table_pagination'; +} from '../../../../../tasks/api_calls/prebuilt_rules'; +import { setRowsPerPageTo } from '../../../../../tasks/table_pagination'; const RULE_NAME = 'Custom rule for bulk actions'; const EUI_SELECTABLE_LIST_ITEM_SR_TEXT = '. To check this option, press Enter.'; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules_actions.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_actions.cy.ts similarity index 89% rename from x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules_actions.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_actions.cy.ts index 7f06d43f4bd960c..386d0be97d2a855 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules_actions.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_actions.cy.ts @@ -6,17 +6,17 @@ */ import type { RuleActionArray } from '@kbn/securitysolution-io-ts-alerting-types'; -import { ROLES } from '../../../../../common/test'; +import { ROLES } from '../../../../../../common/test'; import { RULES_BULK_EDIT_ACTIONS_INFO, RULES_BULK_EDIT_ACTIONS_WARNING, ADD_RULE_ACTIONS_MENU_ITEM, -} from '../../../../screens/rules_bulk_actions'; -import { actionFormSelector } from '../../../../screens/common/rule_actions'; +} from '../../../../../screens/rules_bulk_actions'; +import { actionFormSelector } from '../../../../../screens/common/rule_actions'; -import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../../../tasks/common'; -import type { RuleActionCustomFrequency } from '../../../../tasks/common/rule_actions'; +import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../../../../tasks/common'; +import type { RuleActionCustomFrequency } from '../../../../../tasks/common/rule_actions'; import { addSlackRuleAction, assertSlackRuleAction, @@ -28,25 +28,25 @@ import { pickCustomFrequencyOption, pickPerRuleRunFrequencyOption, pickSummaryOfAlertsOption, -} from '../../../../tasks/common/rule_actions'; +} from '../../../../../tasks/common/rule_actions'; import { waitForRulesTableToBeLoaded, selectNumberOfRules, goToEditRuleActionsSettingsOf, -} from '../../../../tasks/alerts_detection_rules'; +} from '../../../../../tasks/alerts_detection_rules'; import { waitForBulkEditActionToFinish, submitBulkEditForm, checkOverwriteRuleActionsCheckbox, openBulkEditRuleActionsForm, openBulkActionsMenu, -} from '../../../../tasks/rules_bulk_actions'; -import { login, visitWithoutDateRange } from '../../../../tasks/login'; +} from '../../../../../tasks/rules_bulk_actions'; +import { login, visitWithoutDateRange } from '../../../../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../../../urls/navigation'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../../../urls/navigation'; -import { createRule } from '../../../../tasks/api_calls/rules'; -import { createSlackConnector } from '../../../../tasks/api_calls/connectors'; +import { createRule } from '../../../../../tasks/api_calls/rules'; +import { createSlackConnector } from '../../../../../tasks/api_calls/connectors'; import { getEqlRule, @@ -55,8 +55,8 @@ import { getNewThresholdRule, getMachineLearningRule, getNewTermsRule, -} from '../../../../objects/rule'; -import { excessivelyInstallAllPrebuiltRules } from '../../../../tasks/api_calls/prebuilt_rules'; +} from '../../../../../objects/rule'; +import { excessivelyInstallAllPrebuiltRules } from '../../../../../tasks/api_calls/prebuilt_rules'; const ruleNameToAssert = 'Custom rule name with actions'; const expectedNumberOfCustomRulesToBeEdited = 7; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules_data_view.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_data_view.cy.ts similarity index 93% rename from x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules_data_view.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_data_view.cy.ts index f3963340c897788..16fd49767fcc4c6 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detections_response/rules_management/bulk_actions/bulk_edit_rules_data_view.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/bulk_actions/bulk_edit_rules_data_view.cy.ts @@ -8,16 +8,16 @@ import { RULES_BULK_EDIT_DATA_VIEWS_WARNING, RULES_BULK_EDIT_OVERWRITE_DATA_VIEW_CHECKBOX, -} from '../../../../screens/rules_bulk_actions'; +} from '../../../../../screens/rules_bulk_actions'; -import { DATA_VIEW_DETAILS, INDEX_PATTERNS_DETAILS } from '../../../../screens/rule_details'; +import { DATA_VIEW_DETAILS, INDEX_PATTERNS_DETAILS } from '../../../../../screens/rule_details'; import { waitForRulesTableToBeLoaded, goToRuleDetails, selectNumberOfRules, goToTheRuleDetailsOf, -} from '../../../../tasks/alerts_detection_rules'; +} from '../../../../../tasks/alerts_detection_rules'; import { typeIndexPatterns, @@ -27,18 +27,18 @@ import { checkOverwriteIndexPatternsCheckbox, openBulkEditAddIndexPatternsForm, openBulkEditDeleteIndexPatternsForm, -} from '../../../../tasks/rules_bulk_actions'; +} from '../../../../../tasks/rules_bulk_actions'; import { hasIndexPatterns, getDetails, assertDetailsNotExist, -} from '../../../../tasks/rule_details'; -import { login, visitWithoutDateRange } from '../../../../tasks/login'; +} from '../../../../../tasks/rule_details'; +import { login, visitWithoutDateRange } from '../../../../../tasks/login'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../../../urls/navigation'; -import { createRule } from '../../../../tasks/api_calls/rules'; -import { cleanKibana, deleteAlertsAndRules, postDataView } from '../../../../tasks/common'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../../../urls/navigation'; +import { createRule } from '../../../../../tasks/api_calls/rules'; +import { cleanKibana, deleteAlertsAndRules, postDataView } from '../../../../../tasks/common'; import { getEqlRule, @@ -46,7 +46,7 @@ import { getNewRule, getNewThresholdRule, getNewTermsRule, -} from '../../../../objects/rule'; +} from '../../../../../objects/rule'; const DATA_VIEW_ID = 'auditbeat'; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/export_rule.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/import_export/export_rule.cy.ts similarity index 87% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/export_rule.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/import_export/export_rule.cy.ts index f089b2991d78204..6c3c1dee6c7ad83 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/export_rule.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/import_export/export_rule.cy.ts @@ -7,13 +7,13 @@ import path from 'path'; -import { expectedExportedRule, getNewRule } from '../../objects/rule'; +import { expectedExportedRule, getNewRule } from '../../../../../objects/rule'; import { TOASTER_BODY, MODAL_CONFIRMATION_BODY, MODAL_CONFIRMATION_BTN, TOASTER, -} from '../../screens/alerts_detection_rules'; +} from '../../../../../screens/alerts_detection_rules'; import { filterByElasticRules, selectNumberOfRules, @@ -22,26 +22,29 @@ import { exportRule, importRules, expectManagementTableRules, -} from '../../tasks/alerts_detection_rules'; -import { bulkExportRules } from '../../tasks/rules_bulk_actions'; -import { createExceptionList, deleteExceptionList } from '../../tasks/api_calls/exceptions'; -import { getExceptionList } from '../../objects/exception'; -import { createRule } from '../../tasks/api_calls/rules'; +} from '../../../../../tasks/alerts_detection_rules'; +import { bulkExportRules } from '../../../../../tasks/rules_bulk_actions'; +import { + createExceptionList, + deleteExceptionList, +} from '../../../../../tasks/api_calls/exceptions'; +import { getExceptionList } from '../../../../../objects/exception'; +import { createRule } from '../../../../../tasks/api_calls/rules'; import { cleanKibana, resetRulesTableState, deleteAlertsAndRules, reload, -} from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; +} from '../../../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../../urls/navigation'; import { createAndInstallMockedPrebuiltRules, getAvailablePrebuiltRulesCount, preventPrebuiltRulesPackageInstallation, -} from '../../tasks/api_calls/prebuilt_rules'; -import { createRuleAssetSavedObject } from '../../helpers/rules'; +} from '../../../../../tasks/api_calls/prebuilt_rules'; +import { createRuleAssetSavedObject } from '../../../../../helpers/rules'; const EXPORTED_RULES_FILENAME = 'rules_export.ndjson'; const exceptionList = getExceptionList(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/import_rules.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/import_export/import_rules.cy.ts similarity index 88% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/import_rules.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/import_export/import_rules.cy.ts index eaa3cc5b989703b..183ab85bbd5d3bf 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/import_rules.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/import_export/import_rules.cy.ts @@ -5,16 +5,16 @@ * 2.0. */ -import { TOASTER } from '../../screens/alerts_detection_rules'; +import { TOASTER } from '../../../../../screens/alerts_detection_rules'; import { expectManagementTableRules, importRules, importRulesWithOverwriteAll, -} from '../../tasks/alerts_detection_rules'; -import { cleanKibana, deleteAlertsAndRules, reload } from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; +} from '../../../../../tasks/alerts_detection_rules'; +import { cleanKibana, deleteAlertsAndRules, reload } from '../../../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../../urls/navigation'; const RULES_TO_IMPORT_FILENAME = 'cypress/fixtures/7_16_rules.ndjson'; describe('Import rules', () => { diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_snoozing.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/snoozing/rule_snoozing.cy.ts similarity index 84% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_snoozing.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/snoozing/rule_snoozing.cy.ts index 20c48ebe9afbf90..08bddea26288a17 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_snoozing.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rule_actions/snoozing/rule_snoozing.cy.ts @@ -6,14 +6,18 @@ */ import { INTERNAL_ALERTING_API_FIND_RULES_PATH } from '@kbn/alerting-plugin/common'; -import type { RuleResponse } from '../../../common/api/detection_engine'; -import { createRule, snoozeRule as snoozeRuleViaAPI } from '../../tasks/api_calls/rules'; -import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { getNewRule } from '../../objects/rule'; -import { ruleDetailsUrl, ruleEditUrl, SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; -import { internalAlertingSnoozeRule } from '../../urls/routes'; -import { RULES_MANAGEMENT_TABLE, RULE_NAME } from '../../screens/alerts_detection_rules'; +import type { RuleResponse } from '../../../../../../common/api/detection_engine'; +import { createRule, snoozeRule as snoozeRuleViaAPI } from '../../../../../tasks/api_calls/rules'; +import { cleanKibana, deleteAlertsAndRules, deleteConnectors } from '../../../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../../../tasks/login'; +import { getNewRule } from '../../../../../objects/rule'; +import { + ruleDetailsUrl, + ruleEditUrl, + SECURITY_DETECTIONS_RULES_URL, +} from '../../../../../urls/navigation'; +import { internalAlertingSnoozeRule } from '../../../../../urls/routes'; +import { RULES_MANAGEMENT_TABLE, RULE_NAME } from '../../../../../screens/alerts_detection_rules'; import { expectRuleSnoozed, expectRuleSnoozedInTable, @@ -25,17 +29,17 @@ import { snoozeRule, snoozeRuleInTable, unsnoozeRuleInTable, -} from '../../tasks/rule_snoozing'; -import { createSlackConnector } from '../../tasks/api_calls/connectors'; -import { duplicateFirstRule, importRules } from '../../tasks/alerts_detection_rules'; -import { goToActionsStepTab } from '../../tasks/create_new_rule'; -import { goToRuleEditSettings } from '../../tasks/rule_details'; -import { actionFormSelector } from '../../screens/common/rule_actions'; -import { RULE_INDICES } from '../../screens/create_new_rule'; -import { addEmailConnectorAndRuleAction } from '../../tasks/common/rule_actions'; -import { saveEditedRule } from '../../tasks/edit_rule'; -import { DISABLED_SNOOZE_BADGE } from '../../screens/rule_snoozing'; -import { TOOLTIP } from '../../screens/common'; +} from '../../../../../tasks/rule_snoozing'; +import { createSlackConnector } from '../../../../../tasks/api_calls/connectors'; +import { duplicateFirstRule, importRules } from '../../../../../tasks/alerts_detection_rules'; +import { goToActionsStepTab } from '../../../../../tasks/create_new_rule'; +import { goToRuleEditSettings } from '../../../../../tasks/rule_details'; +import { actionFormSelector } from '../../../../../screens/common/rule_actions'; +import { RULE_INDICES } from '../../../../../screens/create_new_rule'; +import { addEmailConnectorAndRuleAction } from '../../../../../tasks/common/rule_actions'; +import { saveEditedRule } from '../../../../../tasks/edit_rule'; +import { DISABLED_SNOOZE_BADGE } from '../../../../../screens/rule_snoozing'; +import { TOOLTIP } from '../../../../../screens/common'; const RULES_TO_IMPORT_FILENAME = 'cypress/fixtures/7_16_rules.ndjson'; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_table_auto_refresh.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_auto_refresh.cy.ts similarity index 86% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_table_auto_refresh.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_auto_refresh.cy.ts index ec553a15c2b2f70..7304972a657908a 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_table_auto_refresh.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_auto_refresh.cy.ts @@ -10,7 +10,7 @@ import { REFRESH_RULES_STATUS, REFRESH_SETTINGS_SWITCH, REFRESH_SETTINGS_SELECTION_NOTE, -} from '../../screens/alerts_detection_rules'; +} from '../../../../screens/alerts_detection_rules'; import { checkAutoRefresh, waitForRulesTableToBeLoaded, @@ -22,19 +22,19 @@ import { disableAutoRefresh, checkAutoRefreshIsDisabled, checkAutoRefreshIsEnabled, -} from '../../tasks/alerts_detection_rules'; -import { login, visit, visitWithoutDateRange } from '../../tasks/login'; +} from '../../../../tasks/alerts_detection_rules'; +import { login, visit, visitWithoutDateRange } from '../../../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; -import { createRule } from '../../tasks/api_calls/rules'; -import { cleanKibana } from '../../tasks/common'; -import { getNewRule } from '../../objects/rule'; -import { setRowsPerPageTo } from '../../tasks/table_pagination'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; +import { createRule } from '../../../../tasks/api_calls/rules'; +import { cleanKibana } from '../../../../tasks/common'; +import { getNewRule } from '../../../../objects/rule'; +import { setRowsPerPageTo } from '../../../../tasks/table_pagination'; const DEFAULT_RULE_REFRESH_INTERVAL_VALUE = 60000; // TODO: See https://github.com/elastic/kibana/issues/154694 -describe.skip('Alerts detection rules table auto-refresh', () => { +describe.skip('Rules table: auto-refresh', () => { before(() => { cleanKibana(); login(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_fiters.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts similarity index 82% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_fiters.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts index 2dd0bc60710720a..5c94cfb3f1bcb95 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rule_fiters.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_filtering.cy.ts @@ -5,24 +5,28 @@ * 2.0. */ -import { cleanKibana, resetRulesTableState, deleteAlertsAndRules } from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; +import { cleanKibana, resetRulesTableState, deleteAlertsAndRules } from '../../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../../tasks/login'; import { expectRulesWithExecutionStatus, filterByExecutionStatus, expectNumberOfRulesShownOnPage, -} from '../../tasks/rule_filters'; +} from '../../../../tasks/rule_filters'; -import { SECURITY_DETECTIONS_RULES_URL } from '../../urls/navigation'; +import { SECURITY_DETECTIONS_RULES_URL } from '../../../../urls/navigation'; -import { waitForRulesTableToBeLoaded } from '../../tasks/alerts_detection_rules'; +import { waitForRulesTableToBeLoaded } from '../../../../tasks/alerts_detection_rules'; -import { createRule, waitForRulesToFinishExecution } from '../../tasks/api_calls/rules'; -import { deleteIndex, createIndex, createDocument } from '../../tasks/api_calls/elasticsearch'; +import { createRule, waitForRulesToFinishExecution } from '../../../../tasks/api_calls/rules'; +import { + deleteIndex, + createIndex, + createDocument, +} from '../../../../tasks/api_calls/elasticsearch'; -import { getNewRule } from '../../objects/rule'; +import { getNewRule } from '../../../../objects/rule'; -describe('Rule management filters', () => { +describe('Rules table: filtering', () => { before(() => { cleanKibana(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/links.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_links.cy.ts similarity index 63% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/links.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_links.cy.ts index 96bcfb7af864aeb..b7fa19531065d5c 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/links.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_links.cy.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { getNewRule } from '../../objects/rule'; -import { RULES_MONITORING_TAB, RULE_NAME } from '../../screens/alerts_detection_rules'; -import { createRule } from '../../tasks/api_calls/rules'; -import { cleanKibana, deleteAlertsAndRules } from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { getNewRule } from '../../../../objects/rule'; +import { RULES_MONITORING_TAB, RULE_NAME } from '../../../../screens/alerts_detection_rules'; +import { createRule } from '../../../../tasks/api_calls/rules'; +import { cleanKibana, deleteAlertsAndRules } from '../../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../../tasks/login'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; -describe('Rules talbes links', () => { +describe('Rules table: links', () => { before(() => { cleanKibana(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/persistent_rules_table_state.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_persistent_state.cy.ts similarity index 95% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/persistent_rules_table_state.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_persistent_state.cy.ts index d063ca348c8d1eb..ef3d23cf7116287 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/persistent_rules_table_state.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_persistent_state.cy.ts @@ -6,16 +6,16 @@ */ import { encode } from '@kbn/rison'; -import { cleanKibana, resetRulesTableState } from '../../tasks/common'; -import { login, visit } from '../../tasks/login'; +import { cleanKibana, resetRulesTableState } from '../../../../tasks/common'; +import { login, visit } from '../../../../tasks/login'; import { DASHBOARDS_URL, KIBANA_HOME, SECURITY_DETECTIONS_RULES_MANAGEMENT_URL, SECURITY_DETECTIONS_RULES_MONITORING_URL, SECURITY_DETECTIONS_RULES_URL, -} from '../../urls/navigation'; -import { getNewRule } from '../../objects/rule'; +} from '../../../../urls/navigation'; +import { getNewRule } from '../../../../objects/rule'; import { filterByCustomRules, filterBySearchTerm, @@ -34,8 +34,8 @@ import { expectFilterByPrebuiltRules, expectFilterByEnabledRules, expectManagementTableRules, -} from '../../tasks/alerts_detection_rules'; -import { createRule } from '../../tasks/api_calls/rules'; +} from '../../../../tasks/alerts_detection_rules'; +import { createRule } from '../../../../tasks/api_calls/rules'; import { expectRowsPerPage, expectTablePage, @@ -43,7 +43,7 @@ import { goToTablePage, setRowsPerPageTo, sortByTableColumn, -} from '../../tasks/table_pagination'; +} from '../../../../tasks/table_pagination'; function createTestRules(): void { createRule(getNewRule({ rule_id: '1', name: 'test 1', tags: ['tag-a'], enabled: false })); @@ -98,7 +98,7 @@ function expectDefaultRulesTableState(): void { expectTablePage(1); } -describe('Persistent rules table state', () => { +describe('Rules table: persistent state', () => { before(() => { cleanKibana(); createTestRules(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_selection.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_selection.cy.ts similarity index 86% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_selection.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_selection.cy.ts index 0e72b6cf7870318..db68e62d923155e 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_selection.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_selection.cy.ts @@ -4,24 +4,24 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { createRuleAssetSavedObject } from '../../helpers/rules'; +import { createRuleAssetSavedObject } from '../../../../helpers/rules'; import { SELECTED_RULES_NUMBER_LABEL, SELECT_ALL_RULES_BTN, SELECT_ALL_RULES_ON_PAGE_CHECKBOX, -} from '../../screens/alerts_detection_rules'; +} from '../../../../screens/alerts_detection_rules'; import { selectNumberOfRules, unselectNumberOfRules, waitForPrebuiltDetectionRulesToBeLoaded, -} from '../../tasks/alerts_detection_rules'; +} from '../../../../tasks/alerts_detection_rules'; import { getAvailablePrebuiltRulesCount, createAndInstallMockedPrebuiltRules, -} from '../../tasks/api_calls/prebuilt_rules'; -import { cleanKibana } from '../../tasks/common'; -import { login, visitWithoutDateRange } from '../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +} from '../../../../tasks/api_calls/prebuilt_rules'; +import { cleanKibana } from '../../../../tasks/common'; +import { login, visitWithoutDateRange } from '../../../../tasks/login'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; const RULE_1 = createRuleAssetSavedObject({ name: 'Test rule 1', @@ -32,7 +32,7 @@ const RULE_2 = createRuleAssetSavedObject({ rule_id: 'rule_2', }); -describe('Rules selection', () => { +describe('Rules table: selection', () => { before(() => { cleanKibana(); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/sorting.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_sorting.cy.ts similarity index 79% rename from x-pack/plugins/security_solution/cypress/e2e/detection_rules/sorting.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_sorting.cy.ts index 36cd0161812530c..66fe81f43c874c7 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/sorting.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/rule_management/rules_table/rules_table_sorting.cy.ts @@ -13,27 +13,31 @@ import { FOURTH_RULE, RULES_MANAGEMENT_TABLE, RULES_ROW, -} from '../../screens/alerts_detection_rules'; +} from '../../../../screens/alerts_detection_rules'; import { enableRule, waitForRulesTableToBeLoaded, waitForRuleToUpdate, -} from '../../tasks/alerts_detection_rules'; -import { login, visit } from '../../tasks/login'; +} from '../../../../tasks/alerts_detection_rules'; +import { login, visit } from '../../../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; -import { createRule } from '../../tasks/api_calls/rules'; -import { cleanKibana } from '../../tasks/common'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../../urls/navigation'; +import { createRule } from '../../../../tasks/api_calls/rules'; +import { cleanKibana } from '../../../../tasks/common'; import { getExistingRule, getNewOverrideRule, getNewRule, getNewThresholdRule, -} from '../../objects/rule'; -import { goToTablePage, setRowsPerPageTo, sortByTableColumn } from '../../tasks/table_pagination'; -import { TABLE_FIRST_PAGE, TABLE_SECOND_PAGE } from '../../screens/table_pagination'; +} from '../../../../objects/rule'; +import { + goToTablePage, + setRowsPerPageTo, + sortByTableColumn, +} from '../../../../tasks/table_pagination'; +import { TABLE_FIRST_PAGE, TABLE_SECOND_PAGE } from '../../../../screens/table_pagination'; -describe('Alerts detection rules', () => { +describe('Rules table: sorting', () => { before(() => { cleanKibana(); login(); diff --git a/x-pack/plugins/security_solution/cypress/e2e/value_lists/value_lists.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_response/value_lists/value_lists.cy.ts similarity index 97% rename from x-pack/plugins/security_solution/cypress/e2e/value_lists/value_lists.cy.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_response/value_lists/value_lists.cy.ts index 719310b80a7eb1a..dbbb9badd8b9df0 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/value_lists/value_lists.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_response/value_lists/value_lists.cy.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { ROLES } from '../../../common/test'; -import { deleteRoleAndUser, login, visitWithoutDateRange } from '../../tasks/login'; -import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../urls/navigation'; +import { ROLES } from '../../../../common/test'; +import { deleteRoleAndUser, login, visitWithoutDateRange } from '../../../tasks/login'; +import { DETECTIONS_RULE_MANAGEMENT_URL } from '../../../urls/navigation'; import { createListsIndex, waitForValueListsModalToBeLoaded, @@ -21,12 +21,12 @@ import { deleteValueListsFile, exportValueList, waitForListsIndex, -} from '../../tasks/lists'; +} from '../../../tasks/lists'; import { VALUE_LISTS_TABLE, VALUE_LISTS_ROW, VALUE_LISTS_MODAL_ACTIVATOR, -} from '../../screens/lists'; +} from '../../../screens/lists'; describe('value lists', () => { describe('management modal', () => { From 31518776161b1766a61b76455b528aadb10b1187 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 25 Jul 2023 21:31:17 +0100 Subject: [PATCH 26/29] chore(NA): update versions after v7.17.13 bump (#162479) This PR is a simple update of our versions file after the recent bumps. --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index afd1d62694e5998..41b5605acb07dac 100644 --- a/versions.json +++ b/versions.json @@ -14,7 +14,7 @@ "previousMinor": true }, { - "version": "7.17.12", + "version": "7.17.13", "branch": "7.17", "previousMajor": true } From 14641e668ee46887a12f1e7ec2603fc68e9b4c3e Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 25 Jul 2023 21:31:31 +0100 Subject: [PATCH 27/29] chore(NA): update versions after v8.9.1 bump (#162480) This PR is a simple update of our versions file after the recent bumps. --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index 41b5605acb07dac..efcd549e2826c33 100644 --- a/versions.json +++ b/versions.json @@ -8,7 +8,7 @@ "currentMinor": true }, { - "version": "8.9.0", + "version": "8.9.1", "branch": "8.9", "currentMajor": true, "previousMinor": true From 3d6dbd4ad791696fbbbca6af96617076e4b6cd32 Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Tue, 25 Jul 2023 23:02:10 +0200 Subject: [PATCH 28/29] [Security Solution] Unified IA Project Navigation (#161667) ## Summary Implementation of serverless-specific pages within the Unified IA Navigation. #### Links implemented: - `Machine Learning` - Landing page created on serverless only - All links in the landing page go to `/ml` app - `Dev Tools` - Links directly to `/dev_tools` app ![snapshot](https://github.com/elastic/kibana/assets/17747913/bd53c796-02df-4c3a-88e4-0fa043b896cd) #### Links not implemented: ```// TODO: in a follow-up PR``` - Project Settings - Change the _Settings_ name by _Project Settings_ - Modify the landing page items according to the design ## Changes ### Plugin contract changes The Machine Learning landing page is the first page that is only available on serverless and should not exist in ess (there are more of this kind in the pipeline), so this PR implements the foundations to enable the _security_solution_serverless_ plugin to implement its own page components, configure the link definition and create new routes to render them in the Security Solution application. These new APIs can be called from either `security_solution_serverless` or `security_solution_ess`, allowing those plugins to have their own offering-specific pages. The new APIs exposed in the security_solution public contract are the following: - `extraAppLinks$`: Observable to add extra app_links into the application links configuration, so they are stored and included in the SecuritySolution plugin `deepLinks` registry, to make them accessible from anywhere in the application using the `chrome.navLinks` API. - `extraRoutes$`: Observable to add extra routes into the main Router, so it can render the new page components. These additional routes are appended after the "sub-plugin" (_alerts_, _timeline_, ...) routes, so it is not possible to override an existing route path. ### New `security-solution-navigation` package Since now we need to use the same navigation components and hooks in different plugins, these functionalities have been extracted to the `@kbn/security-solution-navigation` package, which all Security plugins will depend on (generic, serverless, and ess). The modules exposed by this package have been extracted from the main security_solution plugin and standardized. They include the Landing pages components (new [storybook](https://ci-artifacts.kibana.dev/storybooks/pr-161667/394abe76676c6a76b2982c1d3f5bb675739c3477/security_solution_packages/index.html?path=/story/landing-links-landing-links-icons-categories--landing-links-icons-categories) available), navigation hooks, and link utilities. Also, some types and constants have been moved to this package. A new context provider has also been created, which needs to be in place in order to use this package. The `` is required for the package functionalities to have access to the Kibana core navigation APIs: `navigateToUrl`, `navigateToApp`, and `getUrlForApp`. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: YulNaumenko --- .eslintrc.js | 1 + .github/CODEOWNERS | 1 + package.json | 1 + tsconfig.base.json | 2 + .../security-solution/navigation/README.mdx | 4 + .../security-solution/navigation/index.ts | 20 ++ .../navigation/jest.config.js | 12 + .../security-solution/navigation/kibana.jsonc | 5 + .../navigation/landing_links.ts} | 4 +- .../security-solution/navigation/links.ts | 16 ++ .../navigation/mocks/context.ts | 19 ++ .../navigation/mocks/navigation.ts | 9 + .../security-solution/navigation/package.json | 6 + .../navigation/src/__mocks__/context.tsx | 19 ++ .../navigation/src/__mocks__/navigation.ts | 20 ++ .../navigation/src/constants.ts | 90 +++++++ .../navigation/src/context.tsx | 22 ++ .../src/landing_links/beta_badge.tsx | 32 +++ .../navigation/src/landing_links/index.ts | 15 ++ .../landing_links_icons.stories.tsx | 109 ++++++++ .../landing_links_icons.test.tsx | 90 +++++++ .../src/landing_links/landing_links_icons.tsx | 98 +++++++ ...landing_links_icons_categories.stories.tsx | 129 +++++++++ .../landing_links_icons_categories.test.tsx | 143 ++++++++++ .../landing_links_icons_categories.tsx | 94 +++++++ .../landing_links_images.stories.tsx | 91 +++++++ .../landing_links_images.test.tsx | 92 +++++++ .../landing_links/landing_links_images.tsx | 111 ++++++++ .../landing_links_images_cards.stories.tsx | 103 ++++++++ .../landing_links_images_cards.test.tsx | 94 +++++++ .../landing_links_images_cards.tsx | 118 +++++++++ .../navigation/src/landing_links/lazy.tsx | 33 +++ .../navigation/src/links.test.tsx | 198 ++++++++++++++ .../navigation/src/links.tsx | 142 ++++++++++ .../navigation/src/navigation.test.ts | 65 +++++ .../navigation/src/navigation.ts | 66 +++++ .../security-solution/navigation/src/types.ts | 63 +++++ .../navigation/tsconfig.json | 20 ++ .../security-solution/side_nav/README.mdx | 2 +- .../security-solution/side_nav/index.ts | 12 +- .../src/solution_side_nav.stories.tsx | 7 +- .../side_nav/src/solution_side_nav.styles.ts | 4 +- .../side_nav/src/solution_side_nav.tsx | 7 +- .../src/solution_side_nav_panel.styles.ts | 2 +- .../src/solution_side_nav_panel.test.tsx | 3 +- .../side_nav/src/solution_side_nav_panel.tsx | 4 +- .../security-solution/side_nav/src/types.ts | 39 +-- .../security-solution/side_nav/tsconfig.json | 1 + .../security_solution/common/constants.ts | 76 +----- .../cypress/screens/security_header.ts | 2 +- .../security_solution/public/app/app.tsx | 30 ++- .../public/app/app_routes.test.tsx | 97 +++++++ .../public/app/app_routes.tsx | 58 +++++ .../app/home/template_wrapper/index.tsx | 11 +- .../security_solution/public/app/index.tsx | 13 +- .../landing_links_icons.test.tsx | 89 ------- .../landing_links/landing_links_icons.tsx | 81 ------ .../landing_links_icons_categories.test.tsx | 132 ---------- .../landing_links_icons_categories.tsx | 66 ----- .../landing_links_images.test.tsx | 158 ----------- .../landing_links/landing_links_images.tsx | 161 ------------ .../public/common/components/link_to/index.ts | 11 +- .../components/links/__mocks__/link_props.tsx | 25 ++ .../common/components/links/index.test.tsx | 23 +- .../public/common/components/links/index.tsx | 80 +----- .../common/components/links/link_props.tsx | 81 ++++++ ...rams.ts => use_url_state_query_params.tsx} | 0 .../security_side_nav/categories.ts | 2 +- .../security_side_nav/security_side_nav.tsx | 6 +- .../tab_navigation/tab_navigation.test.tsx | 24 +- .../public/common/icons/cloud_defend.tsx | 6 +- .../public/common/lib/kibana/hooks.ts | 67 +---- .../common/lib/kibana/kibana_react.mock.ts | 7 +- .../public/common/lib/telemetry/constants.ts | 61 +++++ .../public/common/lib/telemetry/index.ts | 60 +---- .../common/lib/telemetry/telemetry_client.ts | 2 +- .../common/lib/telemetry/telemetry_events.ts | 2 +- .../lib/telemetry/telemetry_service.test.ts | 2 +- .../public/common/lib/telemetry/track.ts | 30 +++ .../public/common/lib/telemetry/trackers.ts | 13 + .../public/common/lib/telemetry/types.ts | 22 +- .../public/common/links/links.ts | 52 +++- .../public/common/links/types.ts | 32 +-- .../mock/endpoint/app_context_render.tsx | 5 +- .../mock/endpoint/app_root_provider.tsx | 50 ++-- .../use_security_dashboards_table.test.tsx | 8 +- .../pages/landing_page/index.test.tsx | 10 +- .../dashboards/pages/landing_page/index.tsx | 13 +- .../public/explore/landing.tsx | 9 +- .../network/components/ip/index.test.tsx | 2 +- .../security_solution/public/helpers.test.tsx | 87 ------- .../security_solution/public/helpers.tsx | 42 +-- .../plugins/security_solution/public/index.ts | 2 +- .../endpoint_hosts/store/middleware.test.ts | 10 +- .../public/management/pages/landing.tsx | 29 ++- .../render_context_providers.tsx | 8 +- .../plugins/security_solution/public/mocks.ts | 9 +- .../security_solution/public/plugin.tsx | 28 +- .../public/plugin_contract.ts | 9 + .../public/rules/landing.tsx | 39 ++- .../security_solution/public/rules/links.ts | 1 + .../field_renderers/field_renderers.test.tsx | 18 +- .../components/netflow/index.test.tsx | 2 +- .../netflow/netflow_row_renderer.test.tsx | 3 +- .../plugins/security_solution/public/types.ts | 6 +- .../plugins/security_solution/tsconfig.json | 5 +- .../common/pli/pli_features.test.ts | 26 -- .../common/pli/pli_features.ts | 9 +- .../common/hooks/__mocks__/use_link_props.ts | 16 -- .../common/hooks/__mocks__/use_nav_links.ts | 9 + .../common/hooks/use_link_props.test.tsx | 157 ----------- .../public/common/hooks/use_link_props.ts | 65 ----- .../public/common/hooks/use_nav_links.ts | 6 + .../public/common/icons/auditbeat.tsx | 29 +++ .../public/common/icons/data_connector.tsx | 36 +++ .../public/common/icons/dev_tools.tsx | 45 ++++ .../public/common/icons/endpoint.tsx | 45 ++++ .../public/common/icons/fleet.tsx | 38 +++ .../public/common/icons/index_management.tsx | 68 +++++ .../public/common/icons/lens.tsx | 54 ++++ .../common/icons/searchable_snapshots.tsx | 73 ++++++ .../public/common/icons/siem.tsx | 46 ++++ .../public/common/icons/spaces.tsx | 56 ++++ .../public/common/lazy_icons.tsx | 32 +++ .../__mocks__/index.tsx} | 17 +- .../__mocks__/services.mock.tsx | 15 +- .../create_services.ts} | 26 +- .../public/common/services/index.tsx | 9 + .../public/common/services/services.tsx | 39 +++ .../public/common/services/types.ts | 15 ++ .../public/get_started/index.tsx | 6 +- .../public/navigation/index.ts | 7 +- .../public/navigation/links/app_links.ts | 15 ++ .../public/navigation/links/constants.ts | 36 +++ .../public/navigation/links/nav.links.test.ts | 121 +++++++++ .../public/navigation/links/nav_links.ts | 81 +++++- .../links/sections/dev_tools_links.ts | 15 ++ .../navigation/links/sections/ml_links.ts | 181 +++++++++++++ .../navigation/links/sections/translations.ts | 246 ++++++++++++++++++ .../public/navigation/links/types.ts | 14 +- .../public/navigation/links/util.ts | 22 ++ .../public/navigation/navigation_tree.test.ts | 205 +++++++++------ .../public/navigation/navigation_tree.ts | 152 +++++++---- .../navigation/side_navigation/categories.ts | 12 +- .../navigation/side_navigation/index.tsx | 12 +- .../navigation/side_navigation/lazy.tsx | 5 +- .../side_navigation/side_navigation.test.tsx | 65 ++++- .../side_navigation/side_navigation.tsx | 19 +- .../use_side_nav_items.test.tsx | 89 +------ .../side_navigation/use_side_nav_items.ts | 77 +----- .../public/pages/machine_learning.tsx | 30 +++ .../public/pages/routes.tsx | 35 +++ .../public/plugin.ts | 8 +- .../public/upselling/register_upsellings.tsx | 3 +- .../tsconfig.json | 3 + yarn.lock | 4 + 156 files changed, 4586 insertions(+), 2023 deletions(-) create mode 100644 x-pack/packages/security-solution/navigation/README.mdx create mode 100644 x-pack/packages/security-solution/navigation/index.ts create mode 100644 x-pack/packages/security-solution/navigation/jest.config.js create mode 100644 x-pack/packages/security-solution/navigation/kibana.jsonc rename x-pack/{plugins/security_solution_serverless/public/navigation/links/index.ts => packages/security-solution/navigation/landing_links.ts} (67%) create mode 100644 x-pack/packages/security-solution/navigation/links.ts create mode 100644 x-pack/packages/security-solution/navigation/mocks/context.ts create mode 100644 x-pack/packages/security-solution/navigation/mocks/navigation.ts create mode 100644 x-pack/packages/security-solution/navigation/package.json create mode 100644 x-pack/packages/security-solution/navigation/src/__mocks__/context.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/__mocks__/navigation.ts create mode 100644 x-pack/packages/security-solution/navigation/src/constants.ts create mode 100644 x-pack/packages/security-solution/navigation/src/context.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/beta_badge.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/index.ts create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.stories.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.test.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.stories.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.test.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.stories.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.test.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.stories.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.test.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/landing_links/lazy.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/links.test.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/links.tsx create mode 100644 x-pack/packages/security-solution/navigation/src/navigation.test.ts create mode 100644 x-pack/packages/security-solution/navigation/src/navigation.ts create mode 100644 x-pack/packages/security-solution/navigation/src/types.ts create mode 100644 x-pack/packages/security-solution/navigation/tsconfig.json create mode 100644 x-pack/plugins/security_solution/public/app/app_routes.test.tsx create mode 100644 x-pack/plugins/security_solution/public/app/app_routes.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons_categories.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons_categories.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_images.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_images.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/links/__mocks__/link_props.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/links/link_props.tsx rename x-pack/plugins/security_solution/public/common/components/navigation/__mocks__/{use_url_state_query_params.ts => use_url_state_query_params.tsx} (100%) create mode 100644 x-pack/plugins/security_solution/public/common/lib/telemetry/constants.ts create mode 100644 x-pack/plugins/security_solution/public/common/lib/telemetry/track.ts create mode 100644 x-pack/plugins/security_solution/public/common/lib/telemetry/trackers.ts delete mode 100644 x-pack/plugins/security_solution_serverless/public/common/hooks/__mocks__/use_link_props.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/common/hooks/__mocks__/use_nav_links.ts delete mode 100644 x-pack/plugins/security_solution_serverless/public/common/hooks/use_link_props.test.tsx delete mode 100644 x-pack/plugins/security_solution_serverless/public/common/hooks/use_link_props.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/auditbeat.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/data_connector.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/dev_tools.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/endpoint.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/fleet.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/index_management.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/lens.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/searchable_snapshots.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/siem.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/icons/spaces.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/lazy_icons.tsx rename x-pack/plugins/security_solution_serverless/public/common/{__mocks__/services.tsx => services/__mocks__/index.tsx} (50%) rename x-pack/plugins/security_solution_serverless/public/common/{ => services}/__mocks__/services.mock.tsx (68%) rename x-pack/plugins/security_solution_serverless/public/common/{services.tsx => services/create_services.ts} (50%) create mode 100644 x-pack/plugins/security_solution_serverless/public/common/services/index.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/services/services.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/common/services/types.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/links/app_links.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/links/constants.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/links/nav.links.test.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/links/sections/dev_tools_links.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/links/sections/ml_links.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/links/sections/translations.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/navigation/links/util.ts create mode 100644 x-pack/plugins/security_solution_serverless/public/pages/machine_learning.tsx create mode 100644 x-pack/plugins/security_solution_serverless/public/pages/routes.tsx diff --git a/.eslintrc.js b/.eslintrc.js index de3adc0913fc98f..08eb498ca60cc6e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1174,6 +1174,7 @@ module.exports = { overrides: [ { files: [ + 'x-pack/packages/security-solution/navigation/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution_ess/**/*.{js,mjs,ts,tsx}', 'x-pack/plugins/security_solution_serverless/**/*.{js,mjs,ts,tsx}', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b316c9f4d913b28..8439db6e3ab64e1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -586,6 +586,7 @@ x-pack/test/security_api_integration/packages/helpers @elastic/kibana-core x-pack/plugins/security @elastic/kibana-security x-pack/plugins/security_solution_ess @elastic/security-solution x-pack/test/cases_api_integration/common/plugins/security_solution @elastic/response-ops +x-pack/packages/security-solution/navigation @elastic/security-threat-hunting-explore x-pack/plugins/security_solution @elastic/security-solution x-pack/plugins/security_solution_serverless @elastic/security-solution x-pack/packages/security-solution/side_nav @elastic/security-threat-hunting-explore diff --git a/package.json b/package.json index ac13d131ab15a0d..5b202bf196dbdfe 100644 --- a/package.json +++ b/package.json @@ -588,6 +588,7 @@ "@kbn/security-plugin": "link:x-pack/plugins/security", "@kbn/security-solution-ess": "link:x-pack/plugins/security_solution_ess", "@kbn/security-solution-fixtures-plugin": "link:x-pack/test/cases_api_integration/common/plugins/security_solution", + "@kbn/security-solution-navigation": "link:x-pack/packages/security-solution/navigation", "@kbn/security-solution-plugin": "link:x-pack/plugins/security_solution", "@kbn/security-solution-serverless": "link:x-pack/plugins/security_solution_serverless", "@kbn/security-solution-side-nav": "link:x-pack/packages/security-solution/side_nav", diff --git a/tsconfig.base.json b/tsconfig.base.json index e5c496811ef2f8b..3c5718da22d8259 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1166,6 +1166,8 @@ "@kbn/security-solution-ess/*": ["x-pack/plugins/security_solution_ess/*"], "@kbn/security-solution-fixtures-plugin": ["x-pack/test/cases_api_integration/common/plugins/security_solution"], "@kbn/security-solution-fixtures-plugin/*": ["x-pack/test/cases_api_integration/common/plugins/security_solution/*"], + "@kbn/security-solution-navigation": ["x-pack/packages/security-solution/navigation"], + "@kbn/security-solution-navigation/*": ["x-pack/packages/security-solution/navigation/*"], "@kbn/security-solution-plugin": ["x-pack/plugins/security_solution"], "@kbn/security-solution-plugin/*": ["x-pack/plugins/security_solution/*"], "@kbn/security-solution-serverless": ["x-pack/plugins/security_solution_serverless"], diff --git a/x-pack/packages/security-solution/navigation/README.mdx b/x-pack/packages/security-solution/navigation/README.mdx new file mode 100644 index 000000000000000..187442651c3d801 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/README.mdx @@ -0,0 +1,4 @@ +## Security Solution Navigation + +This package provides resources to be used for Security Solution navigation + diff --git a/x-pack/packages/security-solution/navigation/index.ts b/x-pack/packages/security-solution/navigation/index.ts new file mode 100644 index 000000000000000..e2acac541a014f5 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { useGetAppUrl, useNavigateTo, useNavigation } from './src/navigation'; +export type { GetAppUrl, NavigateTo } from './src/navigation'; +export { NavigationProvider } from './src/context'; +export { SecurityPageName, LinkCategoryType } from './src/constants'; +export type { + NavigationLink, + LinkCategories, + LinkCategory, + TitleLinkCategory, + SeparatorLinkCategory, + AccordionLinkCategory, +} from './src/types'; +export { isAccordionLinkCategory, isSeparatorLinkCategory, isTitleLinkCategory } from './src/types'; diff --git a/x-pack/packages/security-solution/navigation/jest.config.js b/x-pack/packages/security-solution/navigation/jest.config.js new file mode 100644 index 000000000000000..a150e2a7b4c9cd9 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/jest.config.js @@ -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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/x-pack/packages/security-solution/navigation'], +}; diff --git a/x-pack/packages/security-solution/navigation/kibana.jsonc b/x-pack/packages/security-solution/navigation/kibana.jsonc new file mode 100644 index 000000000000000..cec9119374006df --- /dev/null +++ b/x-pack/packages/security-solution/navigation/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/security-solution-navigation", + "owner": "@elastic/security-threat-hunting-explore" +} diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/index.ts b/x-pack/packages/security-solution/navigation/landing_links.ts similarity index 67% rename from x-pack/plugins/security_solution_serverless/public/navigation/links/index.ts rename to x-pack/packages/security-solution/navigation/landing_links.ts index 7271c36bbdfdf47..aa12c9a8a8b2bc7 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/links/index.ts +++ b/x-pack/packages/security-solution/navigation/landing_links.ts @@ -4,5 +4,5 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -export { getProjectNavLinks$ } from './nav_links'; -export type { ProjectNavLinks, ProjectNavigationLink } from './types'; + +export * from './src/landing_links'; diff --git a/x-pack/packages/security-solution/navigation/links.ts b/x-pack/packages/security-solution/navigation/links.ts new file mode 100644 index 000000000000000..cbbe676fcd4ac40 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/links.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. + */ + +export { + useGetLinkUrl, + useGetLinkProps, + withLink, + LinkButton, + LinkAnchor, + isExternalId, +} from './src/links'; +export type { GetLinkUrl, GetLinkProps, LinkProps } from './src/links'; diff --git a/x-pack/packages/security-solution/navigation/mocks/context.ts b/x-pack/packages/security-solution/navigation/mocks/context.ts new file mode 100644 index 000000000000000..20726f8005678ee --- /dev/null +++ b/x-pack/packages/security-solution/navigation/mocks/context.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 type { CoreStart } from '@kbn/core/public'; + +export const mockGetUrlForApp = jest.fn(); +export const mockNavigateToApp = jest.fn(); +export const mockNavigateToUrl = jest.fn(); + +export const mockCoreStart = { + application: { + getUrlForApp: mockGetUrlForApp, + navigateToApp: mockNavigateToApp, + navigateToUrl: mockNavigateToUrl, + }, +} as unknown as CoreStart; diff --git a/x-pack/packages/security-solution/navigation/mocks/navigation.ts b/x-pack/packages/security-solution/navigation/mocks/navigation.ts new file mode 100644 index 000000000000000..74c3ec2ba0663b5 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/mocks/navigation.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const mockGetAppUrl = jest.fn(); +export const mockNavigateTo = jest.fn(); diff --git a/x-pack/packages/security-solution/navigation/package.json b/x-pack/packages/security-solution/navigation/package.json new file mode 100644 index 000000000000000..8170a942224b406 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/security-solution-navigation", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0" +} \ No newline at end of file diff --git a/x-pack/packages/security-solution/navigation/src/__mocks__/context.tsx b/x-pack/packages/security-solution/navigation/src/__mocks__/context.tsx new file mode 100644 index 000000000000000..763eb1bb1d3b5a0 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/__mocks__/context.tsx @@ -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 React, { createContext } from 'react'; +import type { CoreStart } from '@kbn/core/public'; +import { mockCoreStart } from '../../mocks/context'; + +const navigationContext = createContext(mockCoreStart); + +export const NavigationProvider: React.FC = ({ children }) => ( + {children} +); + +export const useNavigationContext = (): CoreStart => { + return mockCoreStart; +}; diff --git a/x-pack/packages/security-solution/navigation/src/__mocks__/navigation.ts b/x-pack/packages/security-solution/navigation/src/__mocks__/navigation.ts new file mode 100644 index 000000000000000..e3a061037a95108 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/__mocks__/navigation.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockGetAppUrl, mockNavigateTo } from '../../mocks/navigation'; + +export const useGetAppUrl = jest.fn(() => { + return { getAppUrl: mockGetAppUrl }; +}); + +export const useNavigateTo = jest.fn(() => { + return { navigateTo: mockNavigateTo }; +}); + +export const useNavigation = jest.fn(() => { + return { navigateTo: mockGetAppUrl, getAppUrl: mockNavigateTo }; +}); diff --git a/x-pack/packages/security-solution/navigation/src/constants.ts b/x-pack/packages/security-solution/navigation/src/constants.ts new file mode 100644 index 000000000000000..1ad8d9683f66a6c --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/constants.ts @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const SECURITY_UI_APP_ID = 'securitySolutionUI' as const; + +export enum SecurityPageName { + administration = 'administration', + alerts = 'alerts', + blocklist = 'blocklist', + /* + * Warning: Computed values are not permitted in an enum with string valued members + * All Cases page names must match `CasesDeepLinkId` in x-pack/plugins/cases/public/common/navigation/deep_links.ts + */ + case = 'cases', // must match `CasesDeepLinkId.cases` + caseConfigure = 'cases_configure', // must match `CasesDeepLinkId.casesConfigure` + caseCreate = 'cases_create', // must match `CasesDeepLinkId.casesCreate` + /* + * Warning: Computed values are not permitted in an enum with string valued members + * All cloud security posture page names must match `CloudSecurityPosturePageId` in x-pack/plugins/cloud_security_posture/public/common/navigation/types.ts + */ + cloudSecurityPostureBenchmarks = 'cloud_security_posture-benchmarks', + cloudSecurityPostureDashboard = 'cloud_security_posture-dashboard', + cloudSecurityPostureFindings = 'cloud_security_posture-findings', + cloudSecurityPostureRules = 'cloud_security_posture-rules', + /* + * Warning: Computed values are not permitted in an enum with string valued members + * All cloud defend page names must match `CloudDefendPageId` in x-pack/plugins/cloud_defend/public/common/navigation/types.ts + */ + cloudDefendPolicies = 'cloud_defend-policies', + dashboards = 'dashboards', + dataQuality = 'data_quality', + detections = 'detections', + detectionAndResponse = 'detection_response', + endpoints = 'endpoints', + eventFilters = 'event_filters', + exceptions = 'exceptions', + exploreLanding = 'explore', + hostIsolationExceptions = 'host_isolation_exceptions', + hosts = 'hosts', + hostsAnomalies = 'hosts-anomalies', + hostsRisk = 'hosts-risk', + hostsEvents = 'hosts-events', + investigate = 'investigate', + kubernetes = 'kubernetes', + landing = 'get_started', + mlLanding = 'machine_learning-landing', // serverless only + network = 'network', + networkAnomalies = 'network-anomalies', + networkDns = 'network-dns', + networkEvents = 'network-events', + networkHttp = 'network-http', + networkTls = 'network-tls', + noPage = '', + overview = 'overview', + policies = 'policy', + responseActionsHistory = 'response_actions_history', + rules = 'rules', + rulesAdd = 'rules-add', + rulesCreate = 'rules-create', + rulesLanding = 'rules-landing', + sessions = 'sessions', + /* + * Warning: Computed values are not permitted in an enum with string valued members + * All threat intelligence page names must match `TIPageId` in x-pack/plugins/threat_intelligence/public/common/navigation/types.ts + */ + threatIntelligenceIndicators = 'threat_intelligence-indicators', + timelines = 'timelines', + timelinesTemplates = 'timelines-templates', + trustedApps = 'trusted_apps', + uncommonProcesses = 'uncommon_processes', + users = 'users', + usersAnomalies = 'users-anomalies', + usersAuthentications = 'users-authentications', + usersEvents = 'users-events', + usersRisk = 'users-risk', + entityAnalytics = 'entity_analytics', + entityAnalyticsManagement = 'entity_analytics-management', + coverageOverview = 'coverage-overview', +} + +export enum LinkCategoryType { + title = 'title', + collapsibleTitle = 'collapsibleTitle', + accordion = 'accordion', + separator = 'separator', +} diff --git a/x-pack/packages/security-solution/navigation/src/context.tsx b/x-pack/packages/security-solution/navigation/src/context.tsx new file mode 100644 index 000000000000000..4daff491cffda3b --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/context.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useContext, createContext } from 'react'; +import type { CoreStart } from '@kbn/core/public'; + +const navigationContext = createContext(null); + +export const NavigationProvider: React.FC<{ core: CoreStart }> = ({ core, children }) => ( + {children} +); + +export const useNavigationContext = (): CoreStart => { + const services = useContext(navigationContext); + if (!services) { + throw new Error('Kibana services not found in navigation context'); + } + return services; +}; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/beta_badge.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/beta_badge.tsx new file mode 100644 index 000000000000000..a8b14b518aed674 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/beta_badge.tsx @@ -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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; +import { EuiBetaBadge, useEuiTheme } from '@elastic/eui'; + +export const BETA = i18n.translate('securitySolutionPackages.beta.label', { + defaultMessage: 'Beta', +}); + +export const BetaBadge = ({ text, className }: { text?: string; className?: string }) => { + const { euiTheme } = useEuiTheme(); + + return ( + + ); +}; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/index.ts b/x-pack/packages/security-solution/navigation/src/landing_links/index.ts new file mode 100644 index 000000000000000..31fcb32783062af --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export type { LandingLinksIconsProps } from './landing_links_icons'; +export type { LandingLinksIconsCategoriesProps } from './landing_links_icons_categories'; +export type { LandingLinksImagesProps } from './landing_links_images'; +export { + LandingLinksIcons, + LandingLinksIconsCategories, + LandingLinksImages, + LandingLinksImageCards, +} from './lazy'; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.stories.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.stories.tsx new file mode 100644 index 000000000000000..1026f9930ecd4ad --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.stories.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 from 'react'; +import type { CoreStart } from '@kbn/core/public'; +import type { NavigationLink } from '../types'; +import type { LandingLinksIconsProps } from './landing_links_icons'; +import { LandingLinksIcons as LandingLinksIconsComponent } from './landing_links_icons'; +import { NavigationProvider } from '../context'; + +const items: NavigationLink[] = [ + { + id: 'link1', + title: 'link #1', + description: 'This is the description of the link #1', + landingIcon: 'addDataApp', + }, + { + id: 'link2', + title: 'link #2', + description: 'This is the description of the link #2', + isBeta: true, + landingIcon: 'securityAnalyticsApp', + }, + { + id: 'link3', + title: 'link #3', + description: 'This is the description of the link #3', + landingIcon: 'spacesApp', + }, + { + id: 'link4', + title: 'link #4', + description: 'This is the description of the link #4', + landingIcon: 'appSearchApp', + }, + { + id: 'link5', + title: 'link #5', + description: 'This is the description of the link #5', + landingIcon: 'heartbeatApp', + }, + { + id: 'link6', + title: 'link #6', + description: 'This is the description of the link #6', + landingIcon: 'lensApp', + }, + { + id: 'link7', + title: 'link #7', + description: 'This is the description of the link #7', + landingIcon: 'timelionApp', + }, + { + id: 'link8', + title: 'link #8', + description: 'This is the description of the link #8', + landingIcon: 'managementApp', + }, +]; + +export default { + title: 'Landing Links/Landing Links Icons', + description: 'Renders the links with icons.', + decorators: [ + (storyFn: Function) => ( +
+ {storyFn()} +
+ ), + ], +}; + +const mockCore = { + application: { + navigateToApp: () => {}, + getUrlForApp: () => '#', + }, +} as unknown as CoreStart; + +export const LandingLinksIcons = (params: LandingLinksIconsProps) => ( +
+ + + +
+); + +LandingLinksIcons.argTypes = { + items: { + control: 'object', + defaultValue: items, + }, +}; + +LandingLinksIcons.parameters = { + layout: 'fullscreen', +}; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.test.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.test.tsx new file mode 100644 index 000000000000000..81b0d828ff1b8cc --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.test.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { SecurityPageName } from '../constants'; +import { mockNavigateTo, mockGetAppUrl } from '../../mocks/navigation'; +import { LandingLinksIcons } from './landing_links_icons'; +import { BETA } from './beta_badge'; + +jest.mock('../navigation'); + +mockGetAppUrl.mockImplementation(({ deepLinkId }: { deepLinkId: string }) => `/${deepLinkId}`); +const mockOnLinkClick = jest.fn(); + +const DEFAULT_NAV_ITEM = { + id: SecurityPageName.overview, + title: 'TEST LABEL', + description: 'TEST DESCRIPTION', + landingIcon: 'myTestIcon', +}; + +describe('LandingLinksIcons', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render items', () => { + const id = SecurityPageName.administration; + const title = 'test label 2'; + const description = 'description 2'; + + const { queryByText } = render( + + ); + + expect(queryByText(DEFAULT_NAV_ITEM.title)).toBeInTheDocument(); + expect(queryByText(DEFAULT_NAV_ITEM.description)).toBeInTheDocument(); + expect(queryByText(title)).toBeInTheDocument(); + expect(queryByText(description)).toBeInTheDocument(); + }); + + it('should render beta', () => { + const { queryByText } = render( + + ); + expect(queryByText(DEFAULT_NAV_ITEM.title)).toBeInTheDocument(); + expect(queryByText(BETA)).toBeInTheDocument(); + }); + + it('should navigate link', () => { + const id = SecurityPageName.administration; + const title = 'test label 2'; + + const { getByText } = render( + + ); + + getByText(title).click(); + + expect(mockGetAppUrl).toHaveBeenCalledWith({ + deepLinkId: SecurityPageName.administration, + absolute: false, + path: '', + }); + expect(mockNavigateTo).toHaveBeenCalledWith({ url: '/administration' }); + }); + + it('should call onLinkClick', () => { + const id = SecurityPageName.administration; + const title = 'myTestLabel'; + + const { getByText } = render( + + ); + + getByText(title).click(); + + expect(mockOnLinkClick).toHaveBeenCalledWith(id); + }); +}); diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.tsx new file mode 100644 index 000000000000000..fc5943f645bd7eb --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons.tsx @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText, EuiTitle, useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; +import { isExternalId, LinkAnchor, type WrappedLinkProps } from '../links'; +import type { NavigationLink } from '../types'; +import { BetaBadge } from './beta_badge'; + +export interface LandingLinksIconsProps { + items: NavigationLink[]; + urlState?: string; + onLinkClick?: (id: string) => void; +} + +const useStyles = () => { + const { euiTheme } = useEuiTheme(); + return { + container: css` + min-width: 22em; + `, + title: css` + margin-top: ${euiTheme.size.m}; + margin-bottom: ${euiTheme.size.s}; + `, + description: css` + max-width: 22em; + `, + }; +}; + +export const LandingLinksIcons: React.FC = ({ + items, + urlState, + onLinkClick, +}) => { + const styles = useStyles(); + return ( + + {items.map(({ id, title, description, landingIcon, isBeta, betaOptions, skipUrlState }) => { + const linkProps: WrappedLinkProps = { + id, + ...(!isExternalId(id) && !skipUrlState && { urlState }), + ...(onLinkClick && { onClick: () => onLinkClick(id) }), + }; + return ( + + + + + + + + + + + +

{title}

+
+
+ {isBeta && ( + + + + )} +
+
+
+ + + {description} + + +
+
+ ); + })} +
+ ); +}; + +// eslint-disable-next-line import/no-default-export +export default LandingLinksIcons; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.stories.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.stories.tsx new file mode 100644 index 000000000000000..52a53e68b62530c --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.stories.tsx @@ -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 React from 'react'; +import type { CoreStart } from '@kbn/core/public'; +import type { NavigationLink } from '../types'; +import type { LandingLinksIconsCategoriesProps } from './landing_links_icons_categories'; +import { LandingLinksIconsCategories as LandingLinksIconsCategoriesComponent } from './landing_links_icons_categories'; +import { NavigationProvider } from '../context'; + +const items: NavigationLink[] = [ + { + id: 'link1', + title: 'link #1', + description: 'This is the description of the link #1', + landingIcon: 'addDataApp', + }, + { + id: 'link2', + title: 'link #2', + description: 'This is the description of the link #2', + isBeta: true, + landingIcon: 'securityAnalyticsApp', + }, + { + id: 'link3', + title: 'link #3', + description: 'This is the description of the link #3', + landingIcon: 'spacesApp', + }, + { + id: 'link4', + title: 'link #4', + description: 'This is the description of the link #4', + landingIcon: 'appSearchApp', + }, + { + id: 'link5', + title: 'link #5', + description: 'This is the description of the link #5', + landingIcon: 'heartbeatApp', + }, + { + id: 'link6', + title: 'link #6', + description: 'This is the description of the link #6', + landingIcon: 'lensApp', + }, + { + id: 'link7', + title: 'link #7', + description: 'This is the description of the link #7', + landingIcon: 'timelionApp', + }, + { + id: 'link8', + title: 'link #8', + description: 'This is the description of the link #8', + landingIcon: 'managementApp', + }, +]; + +export default { + title: 'Landing Links/Landing Links Icons Categories', + description: 'Renders the links with icons grouped by categories.', + decorators: [ + (storyFn: Function) => ( +
+ {storyFn()} +
+ ), + ], +}; + +const mockCore = { + application: { + navigateToApp: () => {}, + getUrlForApp: () => '#', + }, +} as unknown as CoreStart; + +export const LandingLinksIconsCategories = (params: LandingLinksIconsCategoriesProps) => ( +
+ + + +
+); + +LandingLinksIconsCategories.argTypes = { + links: { + control: 'object', + defaultValue: items, + }, + categories: { + control: 'object', + defaultValue: [ + { + type: 'title', + label: 'First category', + linkIds: ['link1', 'link2', 'link3'], + }, + { + label: 'Second category', + type: 'title', + linkIds: ['link4'], + }, + { + label: 'Third category', + type: 'title', + linkIds: ['link5', 'link6', 'link7', 'link8'], + }, + ], + }, +}; + +LandingLinksIconsCategories.parameters = { + layout: 'fullscreen', +}; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.test.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.test.tsx new file mode 100644 index 000000000000000..878d438e72bedbb --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.test.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { SecurityPageName } from '../constants'; +import { mockNavigateTo, mockGetAppUrl } from '../../mocks/navigation'; +import type { LinkCategories, NavigationLink } from '../types'; +import { LandingLinksIconsCategories } from './landing_links_icons_categories'; +import { BETA } from './beta_badge'; + +jest.mock('../navigation'); + +mockGetAppUrl.mockImplementation(({ deepLinkId }: { deepLinkId: string }) => `/${deepLinkId}`); +const mockOnLinkClick = jest.fn(); + +const RULES_ITEM_LABEL = 'elastic rules!'; +const EXCEPTIONS_ITEM_LABEL = 'exceptional!'; +const HOSTS_ITEM_LABEL = 'hosts!!'; +const CATEGORY_1_LABEL = 'first tests category'; +const CATEGORY_2_LABEL = 'second tests category'; + +const categories: LinkCategories = [ + { + label: CATEGORY_1_LABEL, + linkIds: [SecurityPageName.rules], + }, + { + label: CATEGORY_2_LABEL, + linkIds: [SecurityPageName.exceptions, SecurityPageName.hosts], + }, +]; + +const links: NavigationLink[] = [ + { + id: SecurityPageName.rules, + title: RULES_ITEM_LABEL, + description: 'rules', + landingIcon: 'testIcon1', + }, + { + id: SecurityPageName.exceptions, + title: EXCEPTIONS_ITEM_LABEL, + description: 'exceptions', + landingIcon: 'testIcon2', + }, + { + id: SecurityPageName.hosts, + title: HOSTS_ITEM_LABEL, + description: 'hosts', + landingIcon: 'testIcon3', + }, +]; + +describe('LandingLinksIconsCategories', () => { + it('should render items', () => { + const { queryByText } = render(); + + expect(queryByText(RULES_ITEM_LABEL)).toBeInTheDocument(); + expect(queryByText(EXCEPTIONS_ITEM_LABEL)).toBeInTheDocument(); + expect(queryByText(HOSTS_ITEM_LABEL)).toBeInTheDocument(); + }); + + it('should render beta', () => { + const link = { ...links[0], isBeta: true }; + const { queryByText } = render( + + ); + expect(queryByText(RULES_ITEM_LABEL)).toBeInTheDocument(); + expect(queryByText(BETA)).toBeInTheDocument(); + }); + + it('should render categories', () => { + const { queryByText } = render(); + + expect(queryByText(CATEGORY_1_LABEL)).toBeInTheDocument(); + expect(queryByText(CATEGORY_2_LABEL)).toBeInTheDocument(); + }); + + it('should render items in the same order as defined', () => { + const testCategories = [ + { ...categories[0], linkIds: [SecurityPageName.hosts, SecurityPageName.exceptions] }, + ]; + const { queryAllByTestId } = render( + + ); + + const renderedItems = queryAllByTestId('LandingItem'); + + expect(renderedItems[0]).toHaveTextContent(HOSTS_ITEM_LABEL); + expect(renderedItems[1]).toHaveTextContent(EXCEPTIONS_ITEM_LABEL); + }); + + it('should not render category items that are not present in links', () => { + const testLinks = [links[0], links[1]]; // no hosts + const { queryByText } = render( + + ); + + expect(queryByText(EXCEPTIONS_ITEM_LABEL)).toBeInTheDocument(); + expect(queryByText(RULES_ITEM_LABEL)).toBeInTheDocument(); + expect(queryByText(HOSTS_ITEM_LABEL)).not.toBeInTheDocument(); + }); + + it('should not render category if all items filtered', () => { + const testLinks = [links[1], links[2]]; // no rules + const { queryByText } = render( + + ); + + expect(queryByText(CATEGORY_2_LABEL)).toBeInTheDocument(); + expect(queryByText(EXCEPTIONS_ITEM_LABEL)).toBeInTheDocument(); + expect(queryByText(HOSTS_ITEM_LABEL)).toBeInTheDocument(); + + expect(queryByText(CATEGORY_1_LABEL)).not.toBeInTheDocument(); + expect(queryByText(RULES_ITEM_LABEL)).not.toBeInTheDocument(); + }); + + it('should navigate link', () => { + const { getByText } = render(); + + getByText(RULES_ITEM_LABEL).click(); + + expect(mockGetAppUrl).toHaveBeenCalledWith({ + deepLinkId: SecurityPageName.rules, + absolute: false, + path: '', + }); + expect(mockNavigateTo).toHaveBeenCalledWith({ url: '/rules' }); + }); + + it('should call onLinkClick', () => { + const { getByText } = render( + + ); + getByText(RULES_ITEM_LABEL).click(); + expect(mockOnLinkClick).toHaveBeenCalledWith(SecurityPageName.rules); + }); +}); diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.tsx new file mode 100644 index 000000000000000..a999d51b2b1075b --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_icons_categories.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 React, { useMemo } from 'react'; +import { css } from '@emotion/react'; +import { EuiHorizontalRule, EuiSpacer, EuiTitle, useEuiTheme } from '@elastic/eui'; +import type { NavigationLink, LinkCategory } from '../types'; +import { LandingLinksIcons } from './landing_links_icons'; +import { LinkCategoryType } from '../constants'; + +export interface LandingLinksIconsCategoriesProps { + links: Readonly; + categories: Readonly; + urlState?: string; + onLinkClick?: (id: string) => void; +} + +type CategoriesLinks = Array<{ type?: LinkCategoryType; label?: string; links: NavigationLink[] }>; + +const useStyles = () => { + const { euiTheme } = useEuiTheme(); + return { + horizontalRule: css` + margin-top: ${euiTheme.size.m}; + margin-bottom: ${euiTheme.size.l}; + `, + }; +}; + +export const LandingLinksIconsCategories: React.FC = React.memo( + function LandingLinksIconsCategories({ links, categories, urlState, onLinkClick }) { + const categoriesLinks = useMemo(() => { + const linksById = Object.fromEntries(links.map((link) => [link.id, link])); + + return categories.reduce((acc, { label, linkIds, type }) => { + const linksItem = linkIds.reduce((linksAcc, linkId) => { + if (linksById[linkId]) { + linksAcc.push(linksById[linkId]); + } + return linksAcc; + }, []); + if (linksItem.length > 0) { + acc.push({ type, label, links: linksItem }); + } + return acc; + }, []); + }, [links, categories]); + + return ( + <> + {categoriesLinks.map( + ({ type = LinkCategoryType.title, label, links: categoryLinks }, index) => ( +
+ + + +
+ ) + )} + + ); + } +); + +const CategoryHeading: React.FC<{ type?: LinkCategoryType; label?: string; index: number }> = + React.memo(function CategoryHeading({ type, label, index }) { + const styles = useStyles(); + return ( + <> + {index > 0 && } + {type === LinkCategoryType.title && ( + <> + +

{label}

+
+ + + )} + {type === LinkCategoryType.separator && index > 0 && ( + + )} + + ); + }); + +// eslint-disable-next-line import/no-default-export +export default LandingLinksIconsCategories; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.stories.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.stories.tsx new file mode 100644 index 000000000000000..6a8b4642bd02b0f --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.stories.tsx @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { CoreStart } from '@kbn/core/public'; +import type { NavigationLink } from '../types'; +import type { LandingLinksImagesProps } from './landing_links_images'; +import { LandingLinksImages as LandingLinksImagesComponent } from './landing_links_images'; +import { NavigationProvider } from '../context'; + +const items: NavigationLink[] = [ + { + id: 'link1', + title: 'link #1', + description: 'This is the description of the link #1', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link2', + title: 'link #2', + description: 'This is the description of the link #2', + isBeta: true, + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link3', + title: 'link #3', + description: 'This is the description of the link #3', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link4', + title: 'link #4', + description: 'This is the description of the link #4', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link5', + title: 'link #5', + description: 'This is the description of the link #5', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, +]; + +export default { + title: 'Landing Links/Landing Links Images', + description: 'Renders the links with images in a vertical layout', + decorators: [ + (storyFn: Function) => ( +
+ {storyFn()} +
+ ), + ], +}; + +const mockCore = { + application: { + navigateToApp: () => {}, + getUrlForApp: () => '#', + }, +} as unknown as CoreStart; + +export const LandingLinksImages = (params: LandingLinksImagesProps) => ( +
+ + + +
+); + +LandingLinksImages.argTypes = { + items: { + control: 'object', + defaultValue: items, + }, +}; + +LandingLinksImages.parameters = { + layout: 'fullscreen', +}; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.test.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.test.tsx new file mode 100644 index 000000000000000..18676c12e9ae3ec --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.test.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { SecurityPageName } from '../constants'; +import { mockNavigateTo, mockGetAppUrl } from '../../mocks/navigation'; +import { LandingLinksImages } from './landing_links_images'; +import { BETA } from './beta_badge'; + +jest.mock('../navigation'); + +mockGetAppUrl.mockImplementation(({ deepLinkId }: { deepLinkId: string }) => `/${deepLinkId}`); +const mockOnLinkClick = jest.fn(); + +const DEFAULT_NAV_ITEM = { + id: SecurityPageName.overview, + title: 'TEST LABEL', + description: 'TEST DESCRIPTION', + landingImage: 'TEST_IMAGE.png', +}; + +describe('LandingLinksImages', () => { + it('should render', () => { + const title = 'test label'; + + const { queryByText } = render(); + + expect(queryByText(title)).toBeInTheDocument(); + }); + + it('should render landingImage', () => { + const landingImage = 'test_image.jpeg'; + const title = 'TEST_LABEL'; + + const { getByTestId } = render( + + ); + + expect(getByTestId('LandingLinksImage')).toHaveAttribute('src', landingImage); + }); + + it('should render beta tag when isBeta is true', () => { + const { queryByText } = render( + + ); + expect(queryByText(BETA)).toBeInTheDocument(); + }); + + it('should not render beta tag when isBeta is false', () => { + const { queryByText } = render(); + expect(queryByText(BETA)).not.toBeInTheDocument(); + }); + + it('should navigate link', () => { + const id = SecurityPageName.administration; + const title = 'test label 2'; + + const { getByText } = render( + + ); + + getByText(title).click(); + + expect(mockGetAppUrl).toHaveBeenCalledWith({ + deepLinkId: SecurityPageName.administration, + absolute: false, + path: '', + }); + expect(mockNavigateTo).toHaveBeenCalledWith({ url: '/administration' }); + }); + + it('should call onLinkClick', () => { + const id = SecurityPageName.administration; + const title = 'myTestLabel'; + + const { getByText } = render( + + ); + + getByText(title).click(); + + expect(mockOnLinkClick).toHaveBeenCalledWith(id); + }); +}); diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.tsx new file mode 100644 index 000000000000000..30afd857d448350 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images.tsx @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { + EuiFlexGroup, + EuiFlexItem, + EuiImage, + EuiPanel, + EuiText, + EuiTitle, + useEuiTheme, +} from '@elastic/eui'; +import React from 'react'; +import { css } from '@emotion/react'; +import { isExternalId, LinkAnchor, type WrappedLinkProps } from '../links'; +import { BetaBadge } from './beta_badge'; +import type { NavigationLink } from '../types'; + +export interface LandingLinksImagesProps { + items: NavigationLink[]; + urlState?: string; + onLinkClick?: (id: string) => void; +} + +const useStyles = () => { + const { euiTheme } = useEuiTheme(); + return { + link: css` + color: inherit; + &:hover { + text-decoration: none; + } + `, + image: css` + align-items: center; + `, + content: css` + padding-left: ${euiTheme.size.s}; + `, + titleContainer: css` + display: flex; + align-items: center; + `, + title: css` + color: ${euiTheme.colors.primaryText}; + align-items: center; + `, + description: css` + padding-top: ${euiTheme.size.xs}; + max-width: 550px; + `, + }; +}; + +export const LandingLinksImages: React.FC = React.memo( + function LandingLinksImages({ items, urlState, onLinkClick }) { + const styles = useStyles(); + return ( + + {items.map( + ({ id, title, description, landingImage, isBeta, betaOptions, skipUrlState }) => { + const linkProps: WrappedLinkProps = { + id, + ...(!isExternalId(id) && !skipUrlState && { urlState }), + ...(onLinkClick && { onClick: () => onLinkClick(id) }), + }; + return ( + + + {/* Empty onClick is to force hover style on `EuiPanel` */} + {}}> + + + {landingImage && ( + + )} + + +
+ +

{title}

+
+ {isBeta && } +
+ + {description} + +
+
+
+
+
+ ); + } + )} +
+ ); + } +); + +// eslint-disable-next-line import/no-default-export +export default LandingLinksImages; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.stories.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.stories.tsx new file mode 100644 index 000000000000000..5a2bed2e576f1e6 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.stories.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 type { CoreStart } from '@kbn/core/public'; +import type { NavigationLink } from '../types'; +import type { LandingLinksImagesProps } from './landing_links_images_cards'; +import { LandingLinksImageCards as LandingLinksImageCardsComponent } from './landing_links_images_cards'; +import { NavigationProvider } from '../context'; + +const items: NavigationLink[] = [ + { + id: 'link1', + title: 'link #1', + description: 'This is the description of the link #1', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link2', + title: 'link #2', + description: 'This is the description of the link #2', + isBeta: true, + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link3', + title: 'link #3', + description: 'This is the description of the link #3', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link4', + title: 'link #4', + description: 'This is the description of the link #4', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link5', + title: 'link #5', + description: 'This is the description of the link #5', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link6', + title: 'link #6', + description: 'This is the description of the link #6', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, + { + id: 'link7', + title: 'link #7', + description: 'This is the description of the link #7', + landingImage: 'https://dummyimage.com/360x200/efefef/000', + }, +]; + +export default { + title: 'Landing Links/Landing Links Image Cards', + description: 'Renders the links with images in a horizontal layout', + decorators: [ + (storyFn: Function) => ( +
+ {storyFn()} +
+ ), + ], +}; + +const mockCore = { + application: { + navigateToApp: () => {}, + getUrlForApp: () => '#', + }, +} as unknown as CoreStart; + +export const LandingLinksImageCards = (params: LandingLinksImagesProps) => ( +
+ + + +
+); + +LandingLinksImageCards.argTypes = { + items: { + control: 'object', + defaultValue: items, + }, +}; + +LandingLinksImageCards.parameters = { + layout: 'fullscreen', +}; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.test.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.test.tsx new file mode 100644 index 000000000000000..e614c99a500d360 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { SecurityPageName } from '../constants'; +import { mockNavigateTo, mockGetAppUrl } from '../../mocks/navigation'; +import { LandingLinksImageCards } from './landing_links_images_cards'; +import { BETA } from './beta_badge'; + +jest.mock('../navigation'); + +mockGetAppUrl.mockImplementation(({ deepLinkId }: { deepLinkId: string }) => `/${deepLinkId}`); +const mockOnLinkClick = jest.fn(); + +const DEFAULT_NAV_ITEM = { + id: SecurityPageName.overview, + title: 'TEST LABEL', + description: 'TEST DESCRIPTION', + landingImage: 'TEST_IMAGE.png', +}; + +describe('LandingLinksImageCards', () => { + it('should render', () => { + const title = 'test label'; + + const { queryByText } = render( + + ); + + expect(queryByText(title)).toBeInTheDocument(); + }); + + it('should render landingImage', () => { + const landingImage = 'test_image.jpeg'; + const title = 'TEST_LABEL'; + + const { getByTestId } = render( + + ); + + expect(getByTestId('LandingImageCard-image')).toHaveAttribute('src', landingImage); + }); + + it('should render beta tag when isBeta is true', () => { + const { queryByText } = render( + + ); + expect(queryByText(BETA)).toBeInTheDocument(); + }); + + it('should not render beta tag when isBeta is false', () => { + const { queryByText } = render(); + expect(queryByText(BETA)).not.toBeInTheDocument(); + }); + + it('should navigate link', () => { + const id = SecurityPageName.administration; + const title = 'test label 2'; + + const { getByText } = render( + + ); + + getByText(title).click(); + + expect(mockGetAppUrl).toHaveBeenCalledWith({ + deepLinkId: SecurityPageName.administration, + absolute: false, + path: '', + }); + expect(mockNavigateTo).toHaveBeenCalledWith({ url: '/administration' }); + }); + + it('should call onLinkClick', () => { + const id = SecurityPageName.administration; + const title = 'myTestLabel'; + + const { getByText } = render( + + ); + + getByText(title).click(); + + expect(mockOnLinkClick).toHaveBeenCalledWith(id); + }); +}); diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.tsx new file mode 100644 index 000000000000000..6dd999c6fdcf38e --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/landing_links_images_cards.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 { + EuiCard, + EuiFlexGroup, + EuiFlexItem, + EuiImage, + EuiText, + EuiTitle, + useEuiTheme, +} from '@elastic/eui'; +import React from 'react'; +import { css } from '@emotion/react'; +import { isExternalId, withLink, type WrappedLinkProps } from '../links'; +import { BetaBadge } from './beta_badge'; +import type { NavigationLink } from '../types'; + +export interface LandingLinksImagesProps { + items: NavigationLink[]; + urlState?: string; + onLinkClick?: (id: string) => void; +} + +const CARD_WIDTH = 320; + +const useStyles = () => { + const { euiTheme } = useEuiTheme(); + return { + container: css` + max-width: ${CARD_WIDTH}px; + `, + card: css` + // Needed to use the primary color in the title underlining on hover + .euiCard__title { + color: ${euiTheme.colors.primaryText}; + } + `, + titleContainer: css` + display: flex; + align-items: center; + `, + title: css` + color: ${euiTheme.colors.primaryText}; + `, + description: css` + padding-top: ${euiTheme.size.xs}; + max-width: 550px; + `, + }; +}; + +const EuiCardWithLink = withLink(EuiCard); + +export const LandingLinksImageCards: React.FC = React.memo( + function LandingLinksImageCards({ items, urlState, onLinkClick }) { + const styles = useStyles(); + return ( + + {items.map( + ({ id, landingImage, title, description, isBeta, betaOptions, skipUrlState }) => { + const linkProps: WrappedLinkProps = { + id, + ...(!isExternalId(id) && !skipUrlState && { urlState }), + ...(onLinkClick && { onClick: () => onLinkClick(id) }), + }; + return ( + + + ) + } + title={ +
+ +

{title}

+
+ {isBeta && } +
+ } + description={ + + {description} + + } + /> +
+ ); + } + )} +
+ ); + } +); + +// eslint-disable-next-line import/no-default-export +export default LandingLinksImageCards; diff --git a/x-pack/packages/security-solution/navigation/src/landing_links/lazy.tsx b/x-pack/packages/security-solution/navigation/src/landing_links/lazy.tsx new file mode 100644 index 000000000000000..1321fa9cfa445de --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/landing_links/lazy.tsx @@ -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 React, { lazy, Suspense } from 'react'; +import { EuiLoadingSpinner } from '@elastic/eui'; + +const centerSpinnerStyle = { display: 'flex', margin: 'auto' }; + +type WithSuspense = (Component: React.ComponentType) => React.FC; +const withSuspense: WithSuspense = (Component) => + function LazyPageWithSuspense(props) { + return ( + }> + + + ); + }; + +const LandingLinksIconsCategoriesLazy = lazy(() => import('./landing_links_icons_categories')); +export const LandingLinksIconsCategories = withSuspense(LandingLinksIconsCategoriesLazy); + +const LandingLinksIconsLazy = lazy(() => import('./landing_links_icons')); +export const LandingLinksIcons = withSuspense(LandingLinksIconsLazy); + +const LandingLinksImagesLazy = lazy(() => import('./landing_links_images')); +export const LandingLinksImages = withSuspense(LandingLinksImagesLazy); + +const LandingLinksImageCardsLazy = lazy(() => import('./landing_links_images_cards')); +export const LandingLinksImageCards = withSuspense(LandingLinksImageCardsLazy); diff --git a/x-pack/packages/security-solution/navigation/src/links.test.tsx b/x-pack/packages/security-solution/navigation/src/links.test.tsx new file mode 100644 index 000000000000000..a1ad8b03f10648f --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/links.test.tsx @@ -0,0 +1,198 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import { render } from '@testing-library/react'; +import { + useGetLinkUrl, + useGetLinkProps, + withLink, + isExternalId, + getAppIdsFromId, + formatPath, + isModified, +} from './links'; +import { mockGetAppUrl, mockNavigateTo } from '../mocks/navigation'; + +jest.mock('./navigation'); + +const URL = '/the/mocked/url'; +mockGetAppUrl.mockReturnValue(URL); + +describe('links', () => { + describe('useGetLinkUrl', () => { + it('should return the correct link URL', () => { + const { result } = renderHook(useGetLinkUrl); + const getLinkUrl = result.current; + + const linkUrl = getLinkUrl({ + id: 'testId', + path: 'testPath', + absolute: false, + urlState: 'testState', + }); + + expect(linkUrl).toEqual(URL); + + // Verify dependencies were called with correct parameters + expect(mockGetAppUrl).toHaveBeenCalledWith({ + deepLinkId: 'testId', + appId: undefined, + path: 'testPath?testState', + absolute: false, + }); + }); + }); + + describe('useGetLinkProps', () => { + it('should return the correct link props', () => { + const { result } = renderHook(useGetLinkProps); + const getLinkProps = result.current; + + const linkProps = getLinkProps({ + id: 'testId', + path: 'testPath', + urlState: 'testState', + onClick: jest.fn(), + }); + + expect(linkProps).toEqual({ + href: URL, + onClick: expect.any(Function), + }); + + const mockEvent = { preventDefault: jest.fn() } as unknown as React.MouseEvent; + linkProps.onClick(mockEvent); + + expect(mockGetAppUrl).toHaveBeenCalledWith({ + deepLinkId: 'testId', + appId: undefined, + path: 'testPath?testState', + absolute: false, + }); + expect(mockNavigateTo).toHaveBeenCalledWith({ url: URL }); + expect(mockEvent.preventDefault).toHaveBeenCalled(); + }); + }); + + describe('withLink', () => { + it('should return a wrapped component with link functionality', () => { + const MockComponent = jest.fn(() =>
); + const WrappedComponent = withLink(MockComponent); + + const wrapper = render(); + + expect(wrapper.queryByTestId('mock-component')).toBeInTheDocument(); + expect(MockComponent).toHaveBeenCalledWith( + expect.objectContaining({ href: URL, onClick: expect.any(Function) }), + {} + ); + + const mockEvent = { preventDefault: jest.fn() }; + // @ts-ignore-next-line + const onClickProp = MockComponent.mock.calls[0][0].onClick; + onClickProp?.(mockEvent); + + expect(mockNavigateTo).toHaveBeenCalled(); + expect(mockEvent.preventDefault).toHaveBeenCalled(); + }); + }); + + describe('isExternalId', () => { + it('should return true for an external id', () => { + const id = 'externalAppId:12345'; + const result = isExternalId(id); + expect(result).toBe(true); + }); + + it('should return false for an internal id', () => { + const id = 'internalId'; + const result = isExternalId(id); + expect(result).toBe(false); + }); + + it('should return true for a root external id', () => { + const id = 'externalAppId:'; + const result = isExternalId(id); + expect(result).toBe(true); + }); + }); + + describe('getAppIdsFromId', () => { + it('should return the correct app and deep link ids for an external id', () => { + const id = 'externalAppId:12345'; + const result = getAppIdsFromId(id); + expect(result).toEqual({ appId: 'externalAppId', deepLinkId: '12345' }); + }); + + it('should return the correct deep link id for an internal id', () => { + const id = 'internalId'; + const result = getAppIdsFromId(id); + expect(result).toEqual({ deepLinkId: 'internalId' }); + }); + + it('should return the correct app id for a root external id', () => { + const id = 'externalAppId:'; + const result = getAppIdsFromId(id); + expect(result).toEqual({ appId: 'externalAppId', deepLinkId: '' }); + }); + }); + + describe('formatPath', () => { + it('should format the path correctly with URL state', () => { + const path = 'testPath'; + const urlState = 'testState'; + const result = formatPath(path, urlState); + expect(result).toEqual('testPath?testState'); + }); + + it('should format the path correctly without URL state', () => { + const path = 'testPath'; + const urlState = ''; + const result = formatPath(path, urlState); + expect(result).toEqual('testPath'); + }); + + it('should format the path correctly with URL state and existing parameters', () => { + const path = 'testPath?existingParam=value'; + const urlState = 'testState'; + const result = formatPath(path, urlState); + expect(result).toEqual('testPath?existingParam=value&testState'); + }); + + it('should format the path correctly with URL state and parameter path', () => { + const path = 'testPath?parameterPath'; + const urlState = 'testState'; + const result = formatPath(path, urlState); + expect(result).toEqual('testPath?parameterPath&testState'); + }); + }); + + describe('isModified', () => { + it('should return true if event has modifier keys', () => { + const event = { + metaKey: true, + altKey: false, + ctrlKey: false, + shiftKey: true, + } as unknown as React.MouseEvent; + const result = isModified(event); + expect(result).toBe(true); + }); + + it('should return false if event has no modifier keys', () => { + const event = { + metaKey: false, + altKey: false, + ctrlKey: false, + shiftKey: false, + } as unknown as React.MouseEvent; + const result = isModified(event); + expect(result).toBe(false); + }); + }); +}); diff --git a/x-pack/packages/security-solution/navigation/src/links.tsx b/x-pack/packages/security-solution/navigation/src/links.tsx new file mode 100644 index 000000000000000..7a55025d7701ecd --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/links.tsx @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { type MouseEventHandler, type MouseEvent, useCallback } from 'react'; +import { EuiButton, EuiLink, type EuiLinkProps } from '@elastic/eui'; +import { useGetAppUrl, useNavigateTo } from './navigation'; + +export interface WrappedLinkProps { + id: string; + path?: string; + urlState?: string; +} + +export interface LinkProps { + onClick: MouseEventHandler; + href: string; +} + +export type GetLinkUrl = ( + params: WrappedLinkProps & { + absolute?: boolean; + urlState?: string; + } +) => string; + +export type GetLinkProps = ( + params: WrappedLinkProps & { + /** + * Optional `onClick` callback prop. + * It is composed within the returned `onClick` function to perform extra actions when the link is clicked. + * It does not override the navigation operation. + **/ + onClick?: MouseEventHandler; + } +) => LinkProps; + +/** + * It returns the `url` to use in link `href`. + */ +export const useGetLinkUrl = () => { + const { getAppUrl } = useGetAppUrl(); + + const getLinkUrl = useCallback( + ({ id, path = '', absolute = false, urlState }) => { + const formattedPath = urlState ? formatPath(path, urlState) : path; + const { appId, deepLinkId } = getAppIdsFromId(id); + return getAppUrl({ deepLinkId, appId, path: formattedPath, absolute }); + }, + [getAppUrl] + ); + + return getLinkUrl; +}; + +/** + * It returns the `onClick` and `href` props to use in link components based on the` deepLinkId` and `path` parameters. + */ +export const useGetLinkProps = (): GetLinkProps => { + const getLinkUrl = useGetLinkUrl(); + const { navigateTo } = useNavigateTo(); + + const getLinkProps = useCallback( + ({ id, path, urlState, onClick: onClickProps }) => { + const url = getLinkUrl({ id, path, urlState }); + return { + href: url, + onClick: (ev: MouseEvent) => { + if (isModified(ev)) { + return; + } + if (onClickProps) { + onClickProps(ev); + } + ev.preventDefault(); + navigateTo({ url }); + }, + }; + }, + [getLinkUrl, navigateTo] + ); + + return getLinkProps; +}; + +/** + * HOC that wraps any Link component and makes it a navigation Link. + */ +export const withLink = >( + Component: React.ComponentType +): React.FC> => + React.memo(function ({ id, path, urlState, onClick: _onClick, ...rest }) { + const getLink = useGetLinkProps(); + const { onClick, href } = getLink({ id, path, urlState, onClick: _onClick }); + return ; + }); + +/** + * Security Solutions internal link button. + * + * `;` + */ +export const LinkButton = withLink(EuiButton); + +/** + * Security Solutions internal link anchor. + * + * `;` + */ +export const LinkAnchor = withLink(EuiLink); + +// Utils + +export const isExternalId = (id: string): boolean => id.includes(':'); + +export const getAppIdsFromId = (id: string): { appId?: string; deepLinkId?: string } => { + if (isExternalId(id)) { + const [appId, deepLinkId] = id.split(':'); + return { appId, deepLinkId }; + } + return { deepLinkId: id }; // undefined `appId` for internal Security Solution links +}; + +export const formatPath = (path: string, urlState: string) => { + const urlStateClean = urlState.replace('?', ''); + const [urlPath, parameterPath] = path.split('?'); + let queryParams = ''; + if (urlStateClean && parameterPath) { + queryParams = `?${parameterPath}&${urlStateClean}`; + } else if (parameterPath) { + queryParams = `?${parameterPath}`; + } else if (urlStateClean) { + queryParams = `?${urlStateClean}`; + } + return `${urlPath}${queryParams}`; +}; + +export const isModified = (event: MouseEvent) => + event.metaKey || event.altKey || event.ctrlKey || event.shiftKey; diff --git a/x-pack/packages/security-solution/navigation/src/navigation.test.ts b/x-pack/packages/security-solution/navigation/src/navigation.test.ts new file mode 100644 index 000000000000000..2875f79956332e2 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/navigation.test.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { useGetAppUrl, useNavigateTo } from './navigation'; +import { mockGetUrlForApp, mockNavigateToApp, mockNavigateToUrl } from '../mocks/context'; +import { renderHook } from '@testing-library/react-hooks'; + +jest.mock('./context'); + +const URL = '/the/mocked/url'; +mockGetUrlForApp.mockReturnValue(URL); + +describe('yourFile', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('useGetAppUrl', () => { + it('returns the correct app URL', () => { + const { result } = renderHook(useGetAppUrl); + const { getAppUrl } = result.current; + + const appUrl = getAppUrl({ appId: 'testAppId', path: 'testPath', absolute: false }); + + expect(appUrl).toEqual(URL); + + expect(mockGetUrlForApp).toHaveBeenCalledWith('testAppId', { + path: 'testPath', + absolute: false, + }); + }); + }); + + describe('useNavigateTo', () => { + it('navigates to the app URL', () => { + const { result } = renderHook(useNavigateTo); + const { navigateTo } = result.current; + + // Call the navigateTo function with test parameters + navigateTo({ appId: 'testAppId', deepLinkId: 'someId', path: 'testPath' }); + + // Verify dependencies were called with correct parameters + expect(mockNavigateToApp).toHaveBeenCalledWith('testAppId', { + deepLinkId: 'someId', + path: 'testPath', + }); + expect(mockNavigateToUrl).not.toHaveBeenCalled(); + }); + + it('navigates to the provided URL', () => { + const { result } = renderHook(useNavigateTo); + const { navigateTo } = result.current; + + // Call the navigateTo function with test parameters + navigateTo({ url: URL }); + + // Verify dependencies were called with correct parameters + expect(mockNavigateToApp).not.toHaveBeenCalled(); + expect(mockNavigateToUrl).toHaveBeenCalledWith(URL); + }); + }); +}); diff --git a/x-pack/packages/security-solution/navigation/src/navigation.ts b/x-pack/packages/security-solution/navigation/src/navigation.ts new file mode 100644 index 000000000000000..bb8e6ae5a6e4e9c --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/navigation.ts @@ -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 type { NavigateToAppOptions } from '@kbn/core/public'; +import { useCallback } from 'react'; +import { SECURITY_UI_APP_ID } from './constants'; +import { useNavigationContext } from './context'; + +export type GetAppUrl = (param: { + appId?: string; + deepLinkId?: string; + path?: string; + absolute?: boolean; +}) => string; +/** + * The `useGetAppUrl` function returns a full URL to the provided page path by using + * kibana's `getUrlForApp()` + */ +export const useGetAppUrl = () => { + const { getUrlForApp } = useNavigationContext().application; + + const getAppUrl = useCallback( + ({ appId = SECURITY_UI_APP_ID, ...options }) => getUrlForApp(appId, options), + [getUrlForApp] + ); + return { getAppUrl }; +}; + +export type NavigateTo = ( + param: { + url?: string; + appId?: string; + } & NavigateToAppOptions +) => void; +/** + * The `navigateTo` function navigates to any app using kibana's `navigateToApp()`. + * When the `{ url: string }` parameter is passed it will navigate using `navigateToUrl()`. + */ +export const useNavigateTo = () => { + const { navigateToApp, navigateToUrl } = useNavigationContext().application; + + const navigateTo = useCallback( + ({ url, appId = SECURITY_UI_APP_ID, ...options }) => { + if (url) { + navigateToUrl(url); + } else { + navigateToApp(appId, options); + } + }, + [navigateToApp, navigateToUrl] + ); + return { navigateTo }; +}; + +/** + * Returns `navigateTo` and `getAppUrl` navigation hooks + */ +export const useNavigation = () => { + const { navigateTo } = useNavigateTo(); + const { getAppUrl } = useGetAppUrl(); + return { navigateTo, getAppUrl }; +}; diff --git a/x-pack/packages/security-solution/navigation/src/types.ts b/x-pack/packages/security-solution/navigation/src/types.ts new file mode 100644 index 000000000000000..655320fbb57578f --- /dev/null +++ b/x-pack/packages/security-solution/navigation/src/types.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { IconType } from '@elastic/eui'; +import { LinkCategoryType } from './constants'; + +export interface NavigationLink { + categories?: LinkCategories; + description?: string; + disabled?: boolean; + id: T; + landingIcon?: IconType; + landingImage?: string; + links?: Array>; + title: string; + sideNavIcon?: IconType; + skipUrlState?: boolean; + unauthorized?: boolean; + isBeta?: boolean; + betaOptions?: { + text: string; + }; +} + +export interface LinkCategory { + linkIds: readonly T[]; + label?: string; + type?: LinkCategoryType; +} + +export interface TitleLinkCategory extends LinkCategory { + type?: LinkCategoryType.title; + label: string; +} + +export interface AccordionLinkCategory extends LinkCategory { + type: LinkCategoryType.accordion; + label: string; +} + +export interface SeparatorLinkCategory extends LinkCategory { + type: LinkCategoryType.separator; +} + +export type LinkCategories = Readonly>>; + +// Type guards + +export const isTitleLinkCategory = (category: LinkCategory): category is TitleLinkCategory => + (category.type == null || category.type === LinkCategoryType.title) && category.label != null; + +export const isAccordionLinkCategory = ( + category: LinkCategory +): category is AccordionLinkCategory => + category.type === LinkCategoryType.accordion && category.label != null; + +export const isSeparatorLinkCategory = ( + category: LinkCategory +): category is SeparatorLinkCategory => category.type === LinkCategoryType.separator; diff --git a/x-pack/packages/security-solution/navigation/tsconfig.json b/x-pack/packages/security-solution/navigation/tsconfig.json new file mode 100644 index 000000000000000..ca3efc566399037 --- /dev/null +++ b/x-pack/packages/security-solution/navigation/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react", + "@emotion/react/types/css-prop", + "@testing-library/jest-dom", + "@testing-library/react" + ] + }, + "include": ["**/*.ts", "**/*.tsx"], + "kbn_references": [ + "@kbn/i18n", + "@kbn/core", + ], + "exclude": ["target/**/*"] +} diff --git a/x-pack/packages/security-solution/side_nav/README.mdx b/x-pack/packages/security-solution/side_nav/README.mdx index 598696e94cef899..c2655d29add38d6 100644 --- a/x-pack/packages/security-solution/side_nav/README.mdx +++ b/x-pack/packages/security-solution/side_nav/README.mdx @@ -17,7 +17,6 @@ Using the `SecurityNav` wrapper provided by `@kbn/shared-ux-page-solution-nav` i children={ } @@ -32,6 +31,7 @@ Both `items` and `footerItems` props are arrays of `SolutionSideNavItem` type. T | `label` (required) | `string` | The label that will be displayed for the link | | `href` (required) | `string` | The path to be used in the link anchor | | `onClick` | `React.MouseEventHandler` | The handler for the click event | +| `position` | `string` (`top` \| `bottom`) | The position of the link in the main panel, defaults: `top` | | `items` | `SolutionSideNavItem[]` | The sub-items that will be displayed in the panel | | `categories` | `Category[]` | The categories to display in the panel for sub-items | | `iconType` | `IconType` | The EUI IconType to be pre-pended to the label | diff --git a/x-pack/packages/security-solution/side_nav/index.ts b/x-pack/packages/security-solution/side_nav/index.ts index c7b234c0a3689c3..acc05924544fcf9 100644 --- a/x-pack/packages/security-solution/side_nav/index.ts +++ b/x-pack/packages/security-solution/side_nav/index.ts @@ -6,13 +6,5 @@ */ export { SolutionSideNav, type SolutionSideNavProps } from './src'; -export { LinkCategoryType, SolutionSideNavItemPosition } from './src/types'; -export type { - SolutionSideNavItem, - LinkCategory, - TitleLinkCategory, - AccordionLinkCategory, - SeparatorLinkCategory, - LinkCategories, - Tracker, -} from './src/types'; +export { SolutionSideNavItemPosition } from './src/types'; +export type { SolutionSideNavItem, Tracker } from './src/types'; diff --git a/x-pack/packages/security-solution/side_nav/src/solution_side_nav.stories.tsx b/x-pack/packages/security-solution/side_nav/src/solution_side_nav.stories.tsx index d3e1f3d1f5792e6..8378d4f491f9cc5 100644 --- a/x-pack/packages/security-solution/side_nav/src/solution_side_nav.stories.tsx +++ b/x-pack/packages/security-solution/side_nav/src/solution_side_nav.stories.tsx @@ -13,7 +13,6 @@ import { type SolutionSideNavProps, type SolutionSideNavItem, SolutionSideNavItemPosition, - LinkCategoryType, } from '..'; const items: SolutionSideNavItem[] = [ @@ -195,15 +194,15 @@ SolutionSideNav.argTypes = { control: 'object', defaultValue: [ { - type: LinkCategoryType.separator, + type: 'separator', linkIds: ['simpleLink', 'panelLink', 'categoriesPanelLink'], }, { - type: LinkCategoryType.separator, + type: 'separator', linkIds: ['linkWrapped'], }, { - type: LinkCategoryType.separator, + type: 'separator', linkIds: ['bottomLink', 'bottomLinkPanel', 'bottomLinkSeparator', 'bottomLinkIcon'], }, ], diff --git a/x-pack/packages/security-solution/side_nav/src/solution_side_nav.styles.ts b/x-pack/packages/security-solution/side_nav/src/solution_side_nav.styles.ts index 6236d6ceff90682..e390c03157ffb32 100644 --- a/x-pack/packages/security-solution/side_nav/src/solution_side_nav.styles.ts +++ b/x-pack/packages/security-solution/side_nav/src/solution_side_nav.styles.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { tint, type EuiThemeComputed } from '@elastic/eui'; +import { transparentize, type EuiThemeComputed } from '@elastic/eui'; import { css } from '@emotion/css'; export const SolutionSideNavItemStyles = (euiTheme: EuiThemeComputed<{}>) => css` @@ -14,7 +14,7 @@ export const SolutionSideNavItemStyles = (euiTheme: EuiThemeComputed<{}>) => css font-weight: ${euiTheme.font.weight.regular}; } &.solutionSideNavItem--isSelected { - background-color: ${tint(euiTheme.colors.lightShade, 0.5)}; + background-color: ${transparentize(euiTheme.colors.lightShade, 0.5)}; & * { font-weight: ${euiTheme.font.weight.medium}; } diff --git a/x-pack/packages/security-solution/side_nav/src/solution_side_nav.tsx b/x-pack/packages/security-solution/side_nav/src/solution_side_nav.tsx index a1cccc470df4587..f9ac3ab3d8ade19 100644 --- a/x-pack/packages/security-solution/side_nav/src/solution_side_nav.tsx +++ b/x-pack/packages/security-solution/side_nav/src/solution_side_nav.tsx @@ -22,8 +22,9 @@ import partition from 'lodash/fp/partition'; import classNames from 'classnames'; import { METRIC_TYPE } from '@kbn/analytics'; import { i18n } from '@kbn/i18n'; +import type { LinkCategories, SeparatorLinkCategory } from '@kbn/security-solution-navigation'; import { SolutionSideNavPanel } from './solution_side_nav_panel'; -import { LinkCategories, SeparatorLinkCategory, SolutionSideNavItemPosition } from './types'; +import { SolutionSideNavItemPosition } from './types'; import type { SolutionSideNavItem, Tracker } from './types'; import { TELEMETRY_EVENT } from './telemetry/const'; import { TelemetryContextProvider, useTelemetryContext } from './telemetry/telemetry_context'; @@ -199,7 +200,7 @@ const SolutionSideNavItems: React.FC = React.memo( } return ( - <> + {categoryIndex !== 0 && } {categoryItems.map((item) => ( = React.memo( /> ))} - + ); })} diff --git a/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.styles.ts b/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.styles.ts index 6992a2329544d14..360078fff26ebae 100644 --- a/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.styles.ts +++ b/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.styles.ts @@ -24,7 +24,7 @@ export const SolutionSideNavPanelStyles = ( bottom: 0; width: ${PANEL_WIDTH}; height: inherit; - z-index: 999; + z-index: 1000; background-color: ${euiTheme.colors.body}; // If the bottom bar is visible add padding to the navigation diff --git a/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.test.tsx b/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.test.tsx index f59c5c7c7230c55..1e532340a26a8ba 100644 --- a/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.test.tsx +++ b/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.test.tsx @@ -12,7 +12,8 @@ import { BETA_LABEL } from './beta_badge'; import { TELEMETRY_EVENT } from './telemetry/const'; import { METRIC_TYPE } from '@kbn/analytics'; import { TelemetryContextProvider } from './telemetry/telemetry_context'; -import { SolutionSideNavItem, LinkCategories, LinkCategoryType } from './types'; +import type { SolutionSideNavItem } from './types'; +import { type LinkCategories, LinkCategoryType } from '@kbn/security-solution-navigation'; const mockUseIsWithinMinBreakpoint = jest.fn(() => true); jest.mock('@elastic/eui', () => { diff --git a/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.tsx b/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.tsx index cbb63f1cf09f625..eaa3027015b799c 100644 --- a/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.tsx +++ b/x-pack/packages/security-solution/side_nav/src/solution_side_nav_panel.tsx @@ -26,12 +26,12 @@ import { import classNames from 'classnames'; import { METRIC_TYPE } from '@kbn/analytics'; import { - type SolutionSideNavItem, type LinkCategories, isAccordionLinkCategory, isTitleLinkCategory, isSeparatorLinkCategory, -} from './types'; +} from '@kbn/security-solution-navigation'; +import type { SolutionSideNavItem } from './types'; import { BetaBadge } from './beta_badge'; import { TELEMETRY_EVENT } from './telemetry/const'; import { useTelemetryContext } from './telemetry/telemetry_context'; diff --git a/x-pack/packages/security-solution/side_nav/src/types.ts b/x-pack/packages/security-solution/side_nav/src/types.ts index de37aec09a70cca..97c83b368c10be8 100644 --- a/x-pack/packages/security-solution/side_nav/src/types.ts +++ b/x-pack/packages/security-solution/side_nav/src/types.ts @@ -8,6 +8,7 @@ import type React from 'react'; import type { UiCounterMetricType } from '@kbn/analytics'; import type { IconType } from '@elastic/eui'; +import type { LinkCategories } from '@kbn/security-solution-navigation'; export enum SolutionSideNavItemPosition { top = 'top', @@ -31,44 +32,6 @@ export interface SolutionSideNavItem { }; } -export enum LinkCategoryType { - title = 'title', - collapsibleTitle = 'collapsibleTitle', - accordion = 'accordion', - separator = 'separator', -} - -export interface LinkCategory { - linkIds: readonly T[]; - label?: string; - type?: LinkCategoryType; -} - -export interface TitleLinkCategory extends LinkCategory { - type?: LinkCategoryType.title; - label: string; -} -export const isTitleLinkCategory = (category: LinkCategory): category is TitleLinkCategory => - (category.type == null || category.type === LinkCategoryType.title) && category.label != null; - -export interface AccordionLinkCategory extends LinkCategory { - type: LinkCategoryType.accordion; - label: string; -} -export const isAccordionLinkCategory = ( - category: LinkCategory -): category is AccordionLinkCategory => - category.type === LinkCategoryType.accordion && category.label != null; - -export interface SeparatorLinkCategory extends LinkCategory { - type: LinkCategoryType.separator; -} -export const isSeparatorLinkCategory = ( - category: LinkCategory -): category is SeparatorLinkCategory => category.type === LinkCategoryType.separator; - -export type LinkCategories = Readonly>>; - export type Tracker = ( type: UiCounterMetricType, event: string | string[], diff --git a/x-pack/packages/security-solution/side_nav/tsconfig.json b/x-pack/packages/security-solution/side_nav/tsconfig.json index 8dfe47eb50cfecd..4468c671f4351ae 100644 --- a/x-pack/packages/security-solution/side_nav/tsconfig.json +++ b/x-pack/packages/security-solution/side_nav/tsconfig.json @@ -17,6 +17,7 @@ "@kbn/i18n", "@kbn/analytics", "@kbn/shared-ux-page-solution-nav", + "@kbn/security-solution-navigation", ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 8716140a63bce05..dedaaf7e5c0a600 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -9,6 +9,8 @@ import { RuleNotifyWhen } from '@kbn/alerting-plugin/common'; import type { AddOptionsListControlProps } from '@kbn/controls-plugin/public'; import * as i18n from './translations'; +export { SecurityPageName } from '@kbn/security-solution-navigation'; + /** * as const * @@ -78,80 +80,6 @@ export const DEFAULT_THREAT_INDEX_KEY = 'securitySolution:defaultThreatIndex' as export const DEFAULT_THREAT_INDEX_VALUE = ['logs-ti_*'] as const; export const DEFAULT_THREAT_MATCH_QUERY = '@timestamp >= "now-30d/d"' as const; -export enum SecurityPageName { - administration = 'administration', - alerts = 'alerts', - blocklist = 'blocklist', - /* - * Warning: Computed values are not permitted in an enum with string valued members - * All Cases page names must match `CasesDeepLinkId` in x-pack/plugins/cases/public/common/navigation/deep_links.ts - */ - case = 'cases', // must match `CasesDeepLinkId.cases` - caseConfigure = 'cases_configure', // must match `CasesDeepLinkId.casesConfigure` - caseCreate = 'cases_create', // must match `CasesDeepLinkId.casesCreate` - /* - * Warning: Computed values are not permitted in an enum with string valued members - * All cloud security posture page names must match `CloudSecurityPosturePageId` in x-pack/plugins/cloud_security_posture/public/common/navigation/types.ts - */ - cloudSecurityPostureBenchmarks = 'cloud_security_posture-benchmarks', - cloudSecurityPostureDashboard = 'cloud_security_posture-dashboard', - cloudSecurityPostureFindings = 'cloud_security_posture-findings', - cloudSecurityPostureRules = 'cloud_security_posture-rules', - /* - * Warning: Computed values are not permitted in an enum with string valued members - * All cloud defend page names must match `CloudDefendPageId` in x-pack/plugins/cloud_defend/public/common/navigation/types.ts - */ - cloudDefendPolicies = 'cloud_defend-policies', - dashboards = 'dashboards', - dataQuality = 'data_quality', - detections = 'detections', - detectionAndResponse = 'detection_response', - endpoints = 'endpoints', - eventFilters = 'event_filters', - exceptions = 'exceptions', - exploreLanding = 'explore', - hostIsolationExceptions = 'host_isolation_exceptions', - hosts = 'hosts', - hostsAnomalies = 'hosts-anomalies', - hostsRisk = 'hosts-risk', - hostsEvents = 'hosts-events', - investigate = 'investigate', - kubernetes = 'kubernetes', - landing = 'get_started', - network = 'network', - networkAnomalies = 'network-anomalies', - networkDns = 'network-dns', - networkEvents = 'network-events', - networkHttp = 'network-http', - networkTls = 'network-tls', - noPage = '', - overview = 'overview', - policies = 'policy', - responseActionsHistory = 'response_actions_history', - rules = 'rules', - rulesAdd = 'rules-add', - rulesCreate = 'rules-create', - rulesLanding = 'rules-landing', - sessions = 'sessions', - /* - * Warning: Computed values are not permitted in an enum with string valued members - * All threat intelligence page names must match `TIPageId` in x-pack/plugins/threat_intelligence/public/common/navigation/types.ts - */ - threatIntelligenceIndicators = 'threat_intelligence-indicators', - timelines = 'timelines', - timelinesTemplates = 'timelines-templates', - trustedApps = 'trusted_apps', - uncommonProcesses = 'uncommon_processes', - users = 'users', - usersAnomalies = 'users-anomalies', - usersAuthentications = 'users-authentications', - usersEvents = 'users-events', - usersRisk = 'users-risk', - entityAnalytics = 'entity-analytics', - entityAnalyticsManagement = 'entity-analytics-management', - coverageOverview = 'coverage-overview', -} - export const EXPLORE_PATH = '/explore' as const; export const DASHBOARDS_PATH = '/dashboards' as const; export const MANAGE_PATH = '/manage' as const; diff --git a/x-pack/plugins/security_solution/cypress/screens/security_header.ts b/x-pack/plugins/security_solution/cypress/screens/security_header.ts index 2720e4e1a60e3fa..60563640425b9a7 100644 --- a/x-pack/plugins/security_solution/cypress/screens/security_header.ts +++ b/x-pack/plugins/security_solution/cypress/screens/security_header.ts @@ -34,7 +34,7 @@ export const OVERVIEW = '[data-test-subj="solutionSideNavPanelLink-overview"]'; export const DETECTION_RESPONSE = '[data-test-subj="solutionSideNavPanelLink-detection_response"]'; -export const ENTITY_ANALYTICS = '[data-test-subj="solutionSideNavPanelLink-entity-analytics"]'; +export const ENTITY_ANALYTICS = '[data-test-subj="solutionSideNavPanelLink-entity_analytics"]'; export const KUBERNETES = '[data-test-subj="solutionSideNavPanelLink-kubernetes"]'; diff --git a/x-pack/plugins/security_solution/public/app/app.tsx b/x-pack/plugins/security_solution/public/app/app.tsx index 56927518092eace..10f4c007f87cab5 100644 --- a/x-pack/plugins/security_solution/public/app/app.tsx +++ b/x-pack/plugins/security_solution/public/app/app.tsx @@ -19,6 +19,7 @@ import type { AppLeaveHandler, AppMountParameters } from '@kbn/core/public'; import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { CellActionsProvider } from '@kbn/cell-actions'; +import { NavigationProvider } from '@kbn/security-solution-navigation'; import { getComments } from '../assistant/get_comments'; import { augmentMessageCodeBlocks, LOCAL_STORAGE_KEY } from '../assistant/helpers'; import { useConversationStore } from '../assistant/use_conversation_store'; @@ -57,13 +58,14 @@ const StartAppComponent: FC = ({ store, theme$, }) => { + const services = useKibana().services; const { i18n, application: { capabilities }, http, triggersActionsUi: { actionTypeRegistry }, uiActions, - } = useKibana().services; + } = services; const { conversations, setConversations } = useConversationStore(); const { defaultAllow, defaultAllowReplacement, setDefaultAllow, setDefaultAllowReplacement } = @@ -108,19 +110,21 @@ const StartAppComponent: FC = ({ - - - + + - {children} - - - + + {children} + + + + diff --git a/x-pack/plugins/security_solution/public/app/app_routes.test.tsx b/x-pack/plugins/security_solution/public/app/app_routes.test.tsx new file mode 100644 index 000000000000000..585323a7b8da9a3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/app/app_routes.test.tsx @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import type { Capabilities } from '@kbn/core/public'; +import { RedirectRoute } from './app_routes'; +import { + allCasesCapabilities, + noCasesCapabilities, + readCasesCapabilities, +} from '../cases_test_utils'; +import { CASES_FEATURE_ID, SERVER_APP_ID } from '../../common/constants'; + +const mockNotFoundPage = jest.fn(() => null); +jest.mock('./404', () => ({ + NotFoundPage: () => mockNotFoundPage(), +})); + +const mockRedirect = jest.fn((_: unknown) => null); +jest.mock('react-router-dom', () => ({ + Redirect: (params: unknown) => mockRedirect(params), +})); + +describe('RedirectRoute', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('RedirectRoute should redirect to overview page when siem and case privileges are all', () => { + const mockCapabilities = { + [SERVER_APP_ID]: { show: true, crud: true }, + [CASES_FEATURE_ID]: allCasesCapabilities(), + } as unknown as Capabilities; + render(); + expect(mockRedirect).toHaveBeenCalledWith({ to: '/get_started' }); + }); + + it('RedirectRoute should redirect to overview page when siem and case privileges are read', () => { + const mockCapabilities = { + [SERVER_APP_ID]: { show: true, crud: false }, + [CASES_FEATURE_ID]: readCasesCapabilities(), + } as unknown as Capabilities; + render(); + expect(mockRedirect).toHaveBeenCalledWith({ to: '/get_started' }); + }); + + it('RedirectRoute should redirect to not_found page when siem and case privileges are off', () => { + const mockCapabilities = { + [SERVER_APP_ID]: { show: false, crud: false }, + [CASES_FEATURE_ID]: noCasesCapabilities(), + } as unknown as Capabilities; + render(); + expect(mockRedirect).not.toHaveBeenCalled(); + expect(mockNotFoundPage).toHaveBeenCalled(); + }); + + it('RedirectRoute should redirect to overview page when siem privilege is read and case privilege is all', () => { + const mockCapabilities = { + [SERVER_APP_ID]: { show: true, crud: false }, + [CASES_FEATURE_ID]: allCasesCapabilities(), + } as unknown as Capabilities; + render(); + expect(mockRedirect).toHaveBeenCalledWith({ to: '/get_started' }); + }); + + it('RedirectRoute should redirect to overview page when siem privilege is read and case privilege is read', () => { + const mockCapabilities = { + [SERVER_APP_ID]: { show: true, crud: false }, + [CASES_FEATURE_ID]: allCasesCapabilities(), + } as unknown as Capabilities; + render(); + expect(mockRedirect).toHaveBeenCalledWith({ to: '/get_started' }); + }); + + it('RedirectRoute should redirect to cases page when siem privilege is none and case privilege is read', () => { + const mockCapabilities = { + [SERVER_APP_ID]: { show: false, crud: false }, + [CASES_FEATURE_ID]: readCasesCapabilities(), + } as unknown as Capabilities; + render(); + expect(mockRedirect).toHaveBeenCalledWith({ to: '/cases' }); + }); + + it('RedirectRoute should redirect to cases page when siem privilege is none and case privilege is all', () => { + const mockCapabilities = { + [SERVER_APP_ID]: { show: false, crud: false }, + [CASES_FEATURE_ID]: allCasesCapabilities(), + } as unknown as Capabilities; + render(); + expect(mockRedirect).toHaveBeenCalledWith({ to: '/cases' }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/app/app_routes.tsx b/x-pack/plugins/security_solution/public/app/app_routes.tsx new file mode 100644 index 000000000000000..17a40c0a11f1329 --- /dev/null +++ b/x-pack/plugins/security_solution/public/app/app_routes.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { RouteProps } from 'react-router-dom'; +import { Redirect } from 'react-router-dom'; +import { EuiLoadingElastic } from '@elastic/eui'; +import { Routes, Route } from '@kbn/shared-ux-router'; +import type { Capabilities } from '@kbn/core/public'; +import useObservable from 'react-use/lib/useObservable'; +import { CASES_FEATURE_ID, CASES_PATH, LANDING_PATH, SERVER_APP_ID } from '../../common/constants'; +import { NotFoundPage } from './404'; +import type { StartServices } from '../types'; + +export interface AppRoutesProps { + services: StartServices; + subPluginRoutes: RouteProps[]; +} + +export const AppRoutes: React.FC = ({ services, subPluginRoutes }) => { + const extraRoutes = useObservable(services.extraRoutes$, null); + + return ( + + {subPluginRoutes.map((route, index) => { + return ; + })} + {extraRoutes?.map((route, index) => { + return ; + }) ?? ( + // `extraRoutes$` have array value (defaults to []), the first render we receive `null` from the useObservable initialization. + // We need to wait until we receive the array value to prevent the fallback redirection to the landing page. + + + + )} + + + + + ); +}; + +export const RedirectRoute = React.memo<{ capabilities: Capabilities }>(function RedirectRoute({ + capabilities, +}) { + if (capabilities[SERVER_APP_ID].show === true) { + return ; + } + if (capabilities[CASES_FEATURE_ID].read_cases === true) { + return ; + } + return ; +}); diff --git a/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx b/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx index 9643efcb8b0b6de..ba2312b1740a1d1 100644 --- a/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx @@ -7,7 +7,7 @@ import React, { useMemo } from 'react'; import styled from 'styled-components'; -import { EuiThemeProvider, useEuiTheme } from '@elastic/eui'; +import { EuiThemeProvider, useEuiTheme, type EuiThemeComputed } from '@elastic/eui'; import { IS_DRAGGING_CLASS_NAME } from '@kbn/securitysolution-t-grid'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; import type { KibanaPageTemplateProps } from '@kbn/shared-ux-page-kibana-template'; @@ -32,16 +32,16 @@ const StyledKibanaPageTemplate = styled(KibanaPageTemplate)< Omit & { $isShowingTimelineOverlay?: boolean; $addBottomPadding?: boolean; + theme: EuiThemeComputed; // using computed EUI theme to be consistent with user profile theming } >` .kbnSolutionNav { - background-color: ${({ theme }) => theme.eui.euiColorEmptyShade}; + background-color: ${({ theme }) => theme.colors.emptyShade}; } .${BOTTOM_BAR_CLASSNAME} { animation: 'none !important'; // disable the default bottom bar slide animation - background: ${({ theme }) => - theme.eui.euiColorEmptyShade}; // Override bottom bar black background + background: ${({ theme }) => theme.colors.emptyShade}; // Override bottom bar black background color: inherit; // Necessary to override the bottom bar 'white text' transform: ${( { $isShowingTimelineOverlay } // Since the bottom bar wraps the whole overlay now, need to override any transforms when it is open @@ -65,7 +65,7 @@ export const SecuritySolutionTemplateWrapper: React.FC - - {subPluginRoutes.map((route, index) => { - return ; - })} - - - - + , element diff --git a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons.test.tsx b/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons.test.tsx deleted file mode 100644 index 7c52423eb4f662a..000000000000000 --- a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons.test.tsx +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { render } from '@testing-library/react'; -import React from 'react'; -import { SecurityPageName } from '../../../app/types'; -import type { NavigationLink } from '../../links/types'; -import { TestProviders } from '../../mock'; -import { LandingLinksIcons } from './landing_links_icons'; -import * as telemetry from '../../lib/telemetry'; - -const DEFAULT_NAV_ITEM: NavigationLink = { - id: SecurityPageName.overview, - title: 'TEST LABEL', - description: 'TEST DESCRIPTION', - landingIcon: 'myTestIcon', -}; -const spyTrack = jest.spyOn(telemetry, 'track'); - -const mockNavigateTo = jest.fn(); -jest.mock('../../lib/kibana', () => { - const originalModule = jest.requireActual('../../lib/kibana'); - return { - ...originalModule, - useNavigateTo: () => ({ - navigateTo: mockNavigateTo, - }), - }; -}); - -jest.mock('../link_to', () => { - const originalModule = jest.requireActual('../link_to'); - return { - ...originalModule, - useGetSecuritySolutionUrl: () => - jest.fn(({ deepLinkId }: { deepLinkId: string }) => `/${deepLinkId}`), - }; -}); - -describe('LandingLinksIcons', () => { - it('renders', () => { - const title = 'test label'; - - const { queryByText } = render( - - - - ); - - expect(queryByText(title)).toBeInTheDocument(); - }); - - it('renders navigation link', () => { - const id = SecurityPageName.administration; - const title = 'myTestLable'; - - const { getByText } = render( - - - - ); - - getByText(title).click(); - - expect(mockNavigateTo).toHaveBeenCalledWith({ url: '/administration' }); - }); - - it('sends telemetry', () => { - const id = SecurityPageName.administration; - const title = 'myTestLable'; - - const { getByText } = render( - - - - ); - - getByText(title).click(); - - expect(spyTrack).toHaveBeenCalledWith( - telemetry.METRIC_TYPE.CLICK, - `${telemetry.TELEMETRY_EVENT.LANDING_CARD}${id}` - ); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons.tsx b/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons.tsx deleted file mode 100644 index cbaa6e46ede30ce..000000000000000 --- a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons.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 { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText, EuiTitle } from '@elastic/eui'; -import React from 'react'; -import styled from 'styled-components'; - -import { NavItemBetaBadge } from '../navigation/nav_item_beta_badge'; -import { SecuritySolutionLinkAnchor, withSecuritySolutionLink } from '../links'; -import type { NavigationLink } from '../../links/types'; -import { METRIC_TYPE, TELEMETRY_EVENT, track } from '../../lib/telemetry'; - -interface LandingLinksImagesProps { - items: NavigationLink[]; -} - -const LandingItem = styled(EuiFlexItem)` - min-width: 22em; -`; -const Title = styled(EuiTitle)` - margin-top: ${({ theme }) => theme.eui.euiSizeM}; - margin-bottom: ${({ theme }) => theme.eui.euiSizeXS}; -`; -const Description = styled(EuiFlexItem)` - max-width: 22em; -`; -const Link = styled.a` - color: inherit; -`; - -const SecuritySolutionLink = withSecuritySolutionLink(Link); - -export const LandingLinksIcons: React.FC = ({ items }) => ( - - {items.map(({ title, description, id, landingIcon, isBeta, betaOptions }) => ( - - - - - - - - - <EuiFlexGroup gutterSize="none"> - <EuiFlexItem grow={false}> - <SecuritySolutionLinkAnchor - deepLinkId={id} - onClick={() => { - track(METRIC_TYPE.CLICK, `${TELEMETRY_EVENT.LANDING_CARD}${id}`); - }} - > - <h2>{title}</h2> - </SecuritySolutionLinkAnchor> - </EuiFlexItem> - {isBeta && ( - <EuiFlexItem grow={false}> - <NavItemBetaBadge text={betaOptions?.text} /> - </EuiFlexItem> - )} - </EuiFlexGroup> - - - - - {description} - - - - - ))} - -); diff --git a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons_categories.test.tsx b/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons_categories.test.tsx deleted file mode 100644 index 2b73e330097e554..000000000000000 --- a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons_categories.test.tsx +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { render } from '@testing-library/react'; -import React from 'react'; -import { SecurityPageName } from '../../../../common'; -import { TestProviders } from '../../mock'; -import { LandingLinksIconsCategories } from './landing_links_icons_categories'; -import type { NavigationLink } from '../../links'; - -const RULES_ITEM_LABEL = 'elastic rules!'; -const EXCEPTIONS_ITEM_LABEL = 'exceptional!'; -const CATEGORY_1_LABEL = 'first tests category'; -const CATEGORY_2_LABEL = 'second tests category'; - -const defaultAppManageLink: NavigationLink = { - id: SecurityPageName.administration, - title: 'admin', - categories: [ - { - label: CATEGORY_1_LABEL, - linkIds: [SecurityPageName.rules], - }, - { - label: CATEGORY_2_LABEL, - linkIds: [SecurityPageName.exceptions], - }, - ], - links: [ - { - id: SecurityPageName.rules, - title: RULES_ITEM_LABEL, - description: '', - landingIcon: 'testIcon1', - }, - { - id: SecurityPageName.exceptions, - title: EXCEPTIONS_ITEM_LABEL, - description: '', - landingIcon: 'testIcon2', - }, - ], -}; - -const mockAppManageLink = jest.fn(() => defaultAppManageLink); -jest.mock('../../links/nav_links', () => ({ - useRootNavLink: () => mockAppManageLink(), -})); - -describe('LandingLinksIconsCategories', () => { - it('should render items', () => { - const { queryByText } = render( - - - - ); - - expect(queryByText(RULES_ITEM_LABEL)).toBeInTheDocument(); - expect(queryByText(EXCEPTIONS_ITEM_LABEL)).toBeInTheDocument(); - }); - - it('should render items in the same order as defined', () => { - mockAppManageLink.mockReturnValueOnce({ - ...defaultAppManageLink, - categories: [ - { - label: '', - linkIds: [SecurityPageName.exceptions, SecurityPageName.rules], - }, - ], - }); - const { queryAllByTestId } = render( - - - - ); - - const renderedItems = queryAllByTestId('LandingItem'); - - expect(renderedItems[0]).toHaveTextContent(EXCEPTIONS_ITEM_LABEL); - expect(renderedItems[1]).toHaveTextContent(RULES_ITEM_LABEL); - }); - - it('should not render category items filtered', () => { - mockAppManageLink.mockReturnValueOnce({ - ...defaultAppManageLink, - categories: [ - { - label: CATEGORY_1_LABEL, - linkIds: [SecurityPageName.rules, SecurityPageName.exceptions], - }, - ], - links: [ - { - id: SecurityPageName.rules, - title: RULES_ITEM_LABEL, - description: '', - landingIcon: 'testIcon1', - }, - ], - }); - const { queryAllByTestId } = render( - - - - ); - - const renderedItems = queryAllByTestId('LandingItem'); - - expect(renderedItems).toHaveLength(1); - expect(renderedItems[0]).toHaveTextContent(RULES_ITEM_LABEL); - }); - - it('should not render category if all items filtered', () => { - mockAppManageLink.mockReturnValueOnce({ - ...defaultAppManageLink, - links: [], - }); - const { queryByText } = render( - - - - ); - - expect(queryByText(CATEGORY_1_LABEL)).not.toBeInTheDocument(); - expect(queryByText(CATEGORY_2_LABEL)).not.toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons_categories.tsx b/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons_categories.tsx deleted file mode 100644 index 7399b59cf706bd0..000000000000000 --- a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_icons_categories.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 React from 'react'; -import { css } from '@emotion/react'; -import { EuiHorizontalRule, EuiSpacer, EuiTitle, useEuiTheme } from '@elastic/eui'; -import type { SecurityPageName } from '../../../../common'; -import type { NavigationLink } from '../../links'; -import { useRootNavLink } from '../../links/nav_links'; -import { LandingLinksIcons } from './landing_links_icons'; - -type CategoriesLinks = Array<{ label?: string; links: NavigationLink[] }>; - -const useCategories = ({ pageName }: { pageName: SecurityPageName }): CategoriesLinks => { - const { links = [], categories = [] } = useRootNavLink(pageName) ?? {}; - const linksById = Object.fromEntries(links.map((link) => [link.id, link])); - - return categories.reduce((acc, { label, linkIds }) => { - const linksItem = linkIds.reduce((linksAcc, linkId) => { - if (linksById[linkId]) { - linksAcc.push(linksById[linkId]); - } - return linksAcc; - }, []); - if (linksItem.length > 0) { - acc.push({ label, links: linksItem }); - } - return acc; - }, []); -}; - -export const LandingLinksIconsCategories = React.memo(function LandingLinksIconsCategories({ - pageName, -}: { - pageName: SecurityPageName; -}) { - const { euiTheme } = useEuiTheme(); - const categories = useCategories({ pageName }); - return ( - <> - {categories.map(({ label, links }, index) => ( -
- {index > 0 && ( - <> - - - - )} - -

{label}

-
- - -
- ))} - - ); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_images.test.tsx b/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_images.test.tsx deleted file mode 100644 index 16da6d597b5ef22..000000000000000 --- a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_images.test.tsx +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { render } from '@testing-library/react'; -import React from 'react'; -import { SecurityPageName } from '../../../app/types'; -import type { NavigationLink } from '../../links/types'; -import { TestProviders } from '../../mock'; -import { LandingLinksImages, LandingImageCards } from './landing_links_images'; -import * as telemetry from '../../lib/telemetry'; - -const BETA = 'Beta'; -const DEFAULT_NAV_ITEM: NavigationLink = { - id: SecurityPageName.overview, - title: 'TEST LABEL', - description: 'TEST DESCRIPTION', - landingImage: 'TEST_IMAGE.png', -}; - -const BETA_NAV_ITEM: NavigationLink = { - id: SecurityPageName.kubernetes, - title: 'TEST LABEL', - description: 'TEST DESCRIPTION', - landingImage: 'TEST_IMAGE.png', - isBeta: true, -}; - -jest.mock('../../lib/kibana/kibana_react', () => { - return { - useKibana: jest.fn().mockReturnValue({ - services: { - application: { - getUrlForApp: jest.fn(), - navigateToApp: jest.fn(), - navigateToUrl: jest.fn(), - }, - }, - }), - }; -}); - -const spyTrack = jest.spyOn(telemetry, 'track'); - -describe('LandingLinksImages', () => { - it('renders', () => { - const title = 'test label'; - - const { queryByText } = render( - - - - ); - - expect(queryByText(title)).toBeInTheDocument(); - }); - - it('renders landingImage', () => { - const landingImage = 'test_image.jpeg'; - const title = 'TEST_LABEL'; - - const { getByTestId } = render( - - - - ); - - expect(getByTestId('LandingLinksImage')).toHaveAttribute('src', landingImage); - }); - - it('renders beta tag when isBeta is true', () => { - const { queryByText } = render( - - - - ); - - expect(queryByText(BETA)).toBeInTheDocument(); - }); - - it('does not render beta tag when isBeta is false', () => { - const { queryByText } = render( - - - - ); - - expect(queryByText(BETA)).not.toBeInTheDocument(); - }); -}); - -describe('LandingImageCards', () => { - it('renders', () => { - const title = 'test label'; - - const { queryByText } = render( - - - - ); - - expect(queryByText(title)).toBeInTheDocument(); - }); - - it('renders landingImage', () => { - const landingImage = 'test_image.jpeg'; - const title = 'TEST_LABEL'; - - const { getByTestId } = render( - - - - ); - - expect(getByTestId('LandingImageCard-image')).toHaveAttribute('src', landingImage); - }); - - it('sends telemetry', () => { - const landingImage = 'test_image.jpeg'; - const title = 'TEST LABEL'; - - const { getByText } = render( - - - - ); - - getByText(title).click(); - - expect(spyTrack).toHaveBeenCalledWith( - telemetry.METRIC_TYPE.CLICK, - `${telemetry.TELEMETRY_EVENT.LANDING_CARD}${DEFAULT_NAV_ITEM.id}` - ); - }); - - it('renders beta tag when isBeta is true', () => { - const { queryByText } = render( - - - - ); - - expect(queryByText(BETA)).toBeInTheDocument(); - }); - - it('does not render beta tag when isBeta is false', () => { - const { queryByText } = render( - - - - ); - - expect(queryByText(BETA)).not.toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_images.tsx b/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_images.tsx deleted file mode 100644 index 0eeb50ccdcdcd60..000000000000000 --- a/x-pack/plugins/security_solution/public/common/components/landing_links/landing_links_images.tsx +++ /dev/null @@ -1,161 +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 { - EuiCard, - EuiFlexGroup, - EuiFlexItem, - EuiImage, - EuiPanel, - EuiText, - EuiTitle, -} from '@elastic/eui'; -import { METRIC_TYPE } from '@kbn/analytics'; -import React from 'react'; -import styled from 'styled-components'; -import { withSecuritySolutionLink } from '../links'; -import { NavItemBetaBadge } from '../navigation/nav_item_beta_badge'; -import type { NavigationLink } from '../../links/types'; -import { TELEMETRY_EVENT, track } from '../../lib/telemetry'; - -interface LandingImagesProps { - items: NavigationLink[]; -} - -const PrimaryEuiTitle = styled(EuiTitle)` - color: ${(props) => props.theme.eui.euiColorPrimary}; -`; - -const LandingLinksDescripton = styled(EuiText)` - padding-top: ${({ theme }) => theme.eui.euiSizeXS}; - max-width: 550px; -`; - -const Link = styled.a` - color: inherit; -`; - -const StyledFlexItem = styled(EuiFlexItem)` - align-items: center; -`; - -const Content = styled(EuiFlexItem)` - padding-left: ${({ theme }) => theme.eui.euiSizeS}; -`; - -const FlexTitle = styled.div` - display: flex; - align-items: center; -`; - -const TitleText = styled.h2` - display: inline; -`; - -const SecuritySolutionLink = withSecuritySolutionLink(Link); - -export const LandingLinksImages: React.FC = ({ items }) => ( - - {items.map(({ title, description, landingImage, id, isBeta, betaOptions }) => ( - - { - track(METRIC_TYPE.CLICK, `${TELEMETRY_EVENT.LANDING_CARD}${id}`); - }} - > - {/* Empty onClick is to force hover style on `EuiPanel` */} - {}}> - - - {landingImage && ( - - )} - - - - - {title} - {isBeta && } - - - - {description} - - - - - - - ))} - -); - -const CARD_WIDTH = 320; -const LandingImageCardItem = styled(EuiFlexItem)` - max-width: ${CARD_WIDTH}px; -`; - -const LandingCardDescription = styled.span` - font-size: ${({ theme }) => theme.eui.euiFontSizeXS}; - 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, landingImage, title, description, isBeta, betaOptions }) => ( - - - ) - } - title={ - - - {title} - {isBeta && } - - - } - description={{description}} - onClick={() => { - track(METRIC_TYPE.CLICK, `${TELEMETRY_EVENT.LANDING_CARD}${id}`); - }} - /> - - ))} - -)); - -LandingImageCards.displayName = 'LandingImageCards'; diff --git a/x-pack/plugins/security_solution/public/common/components/link_to/index.ts b/x-pack/plugins/security_solution/public/common/components/link_to/index.ts index 6b29af13f882704..5ef5280df7fa010 100644 --- a/x-pack/plugins/security_solution/public/common/components/link_to/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/link_to/index.ts @@ -7,6 +7,7 @@ import { isEmpty } from 'lodash/fp'; import { useCallback } from 'react'; +import { useGetLinkUrl } from '@kbn/security-solution-navigation/links'; import { useUrlStateQueryParams, useGetUrlStateQueryParams, @@ -66,17 +67,15 @@ export type GetSecuritySolutionUrl = (param: { }) => string; export const useGetSecuritySolutionUrl = () => { - const { getAppUrl } = useAppUrl(); + const getLinkUrl = useGetLinkUrl(); const getUrlStateQueryParams = useGetUrlStateQueryParams(); const getSecuritySolutionUrl = useCallback( ({ deepLinkId, path = '', absolute = false, skipSearch = false }) => { - const search = getUrlStateQueryParams(deepLinkId); - const formattedPath = formatPath(path, search, skipSearch); - - return getAppUrl({ deepLinkId, path: formattedPath, absolute }); + const urlState: string = skipSearch ? '' : getUrlStateQueryParams(deepLinkId); + return getLinkUrl({ id: deepLinkId, path, urlState, absolute }); }, - [getAppUrl, getUrlStateQueryParams] + [getLinkUrl, getUrlStateQueryParams] ); return getSecuritySolutionUrl; diff --git a/x-pack/plugins/security_solution/public/common/components/links/__mocks__/link_props.tsx b/x-pack/plugins/security_solution/public/common/components/links/__mocks__/link_props.tsx new file mode 100644 index 000000000000000..21f9add550b54dc --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/links/__mocks__/link_props.tsx @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +export const useSecuritySolutionLinkProps = jest.fn(({ path }: { path: string }) => ({ + href: path || '', + onClick: () => {}, +})); +export const useGetSecuritySolutionLinkProps = () => useSecuritySolutionLinkProps; + +export const withSecuritySolutionLink = >( + WrappedComponent: React.ComponentType +) => + function WithSecuritySolutionLink({ path, ...rest }: Omit & { path: string }) { + return ( + + ); + }; diff --git a/x-pack/plugins/security_solution/public/common/components/links/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/links/index.test.tsx index 44aaab1432ee784..b5cad129225d2ec 100644 --- a/x-pack/plugins/security_solution/public/common/components/links/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/links/index.test.tsx @@ -28,27 +28,16 @@ import { SecuritySolutionLinkButton, } from '.'; import { SecurityPageName } from '../../../app/types'; +import { mockGetAppUrl, mockNavigateTo } from '@kbn/security-solution-navigation/mocks/navigation'; -jest.mock('../link_to'); +jest.mock('@kbn/security-solution-navigation/src/navigation'); +jest.mock('../navigation/use_url_state_query_params'); jest.mock('../../../overview/components/events_by_dataset'); -const mockNavigateTo = jest.fn(); -jest.mock('../../lib/kibana', () => { - return { - useUiSetting$: jest.fn(), - useKibana: () => ({ - services: { - application: { - navigateToApp: jest.fn(), - }, - }, - }), - useNavigateTo: () => ({ - navigateTo: mockNavigateTo, - }), - }; -}); +jest.mock('../../lib/kibana'); + +mockGetAppUrl.mockImplementation(({ path }) => path); describe('Custom Links', () => { const hostName = 'Host Name'; diff --git a/x-pack/plugins/security_solution/public/common/components/links/index.tsx b/x-pack/plugins/security_solution/public/common/components/links/index.tsx index a3c47bff34247c7..4f07d53023e9e79 100644 --- a/x-pack/plugins/security_solution/public/common/components/links/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/links/index.tsx @@ -7,7 +7,7 @@ import type { EuiButtonEmpty, EuiButtonIcon } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiToolTip } from '@elastic/eui'; -import type { SyntheticEvent, MouseEventHandler, MouseEvent } from 'react'; +import type { SyntheticEvent, MouseEvent } from 'react'; import React, { useMemo, useCallback, useEffect } from 'react'; import { isArray, isNil } from 'lodash/fp'; import { GuidedOnboardingTourStep } from '../guided_onboarding_tour/tour_step'; @@ -22,11 +22,10 @@ import { getNetworkDetailsUrl, getCreateCaseUrl, useFormatUrl, - useGetSecuritySolutionUrl, } from '../link_to'; import type { FlowTargetSourceDest } from '../../../../common/search_strategy/security_solution/network'; import { FlowTarget } from '../../../../common/search_strategy/security_solution/network'; -import { useUiSetting$, useKibana, useNavigateTo } from '../../lib/kibana'; +import { useUiSetting$, useKibana } from '../../lib/kibana'; import { isUrlInvalid } from '../../utils/validators'; import * as i18n from './translations'; @@ -43,17 +42,18 @@ import { } from './helpers'; import type { HostsTableType } from '../../../explore/hosts/store/model'; import type { UsersTableType } from '../../../explore/users/store/model'; +import { useGetSecuritySolutionLinkProps, withSecuritySolutionLink } from './link_props'; +export { useSecuritySolutionLinkProps, type GetSecuritySolutionLinkProps } from './link_props'; export { LinkButton, LinkAnchor } from './helpers'; +export { useGetSecuritySolutionLinkProps, withSecuritySolutionLink }; + export const DEFAULT_NUMBER_OF_LINK = 5; /** The default max-height of the Reputation Links popover used to show "+n More" items (e.g. `+9 More`) */ export const DEFAULT_MORE_MAX_HEIGHT = '200px'; -const isModified = (event: MouseEvent) => - event.metaKey || event.altKey || event.ctrlKey || event.shiftKey; - // Internal Links const UserDetailsLinkComponent: React.FC<{ children?: React.ReactNode; @@ -577,74 +577,6 @@ export const WhoIsLink = React.memo<{ children?: React.ReactNode; domain: string WhoIsLink.displayName = 'WhoIsLink'; -interface SecuritySolutionLinkProps { - deepLinkId: SecurityPageName; - path?: string; -} - -interface LinkProps { - onClick: MouseEventHandler; - href: string; -} - -export type GetSecuritySolutionProps = ( - params: SecuritySolutionLinkProps & { onClick?: MouseEventHandler } -) => LinkProps; - -/** - * It returns the `onClick` and `href` props to use in link components based on the` deepLinkId` and `path` parameters. - */ -export const useGetSecuritySolutionLinkProps = (): GetSecuritySolutionProps => { - const getSecuritySolutionUrl = useGetSecuritySolutionUrl(); - const { navigateTo } = useNavigateTo(); - - const getSecuritySolutionProps = useCallback( - ({ deepLinkId, path, onClick: onClickProps }) => { - const url = getSecuritySolutionUrl({ deepLinkId, path }); - return { - href: url, - onClick: (ev: MouseEvent) => { - if (isModified(ev)) { - return; - } - - ev.preventDefault(); - navigateTo({ url }); - if (onClickProps) { - onClickProps(ev); - } - }, - }; - }, - [getSecuritySolutionUrl, navigateTo] - ); - - return getSecuritySolutionProps; -}; - -/** - * HOC that wraps any Link component and makes it a Security solutions internal navigation Link. - */ -export const withSecuritySolutionLink = >( - WrappedComponent: React.FC -) => { - const SecuritySolutionLink: React.FC> = ({ - deepLinkId, - path, - onClick: onClickProps, - ...rest - }) => { - const getSecuritySolutionLinkProps = useGetSecuritySolutionLinkProps(); - const { onClick, href } = getSecuritySolutionLinkProps({ - deepLinkId, - path, - onClick: onClickProps, - }); - return ; - }; - return SecuritySolutionLink; -}; - /** * Security Solutions internal link button. * diff --git a/x-pack/plugins/security_solution/public/common/components/links/link_props.tsx b/x-pack/plugins/security_solution/public/common/components/links/link_props.tsx new file mode 100644 index 000000000000000..23fe1c963c0f040 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/links/link_props.tsx @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo, type MouseEventHandler } from 'react'; +import { useGetLinkProps, withLink, type LinkProps } from '@kbn/security-solution-navigation/links'; +import { useGetUrlStateQueryParams } from '../navigation/use_url_state_query_params'; +import type { SecurityPageName } from '../../../../common/constants'; + +interface SecuritySolutionLinkProps { + deepLinkId: SecurityPageName; + path?: string; +} + +type GetSecuritySolutionLinkPropsParams = SecuritySolutionLinkProps & { + /** + * Optional `onClick` callback prop. + * It is composed within the returned `onClick` function to perform extra actions when the link is clicked. + * It does not override the navigation operation. + **/ + onClick?: MouseEventHandler; +}; + +export type GetSecuritySolutionLinkProps = ( + params: GetSecuritySolutionLinkPropsParams +) => LinkProps; + +/** + * It returns a function to get the `onClick` and `href` props to use in link components + * based on the` deepLinkId` and `path` parameters. + */ +export const useGetSecuritySolutionLinkProps = (): GetSecuritySolutionLinkProps => { + const getLinkProps = useGetLinkProps(); + const getUrlStateQueryParams = useGetUrlStateQueryParams(); + + const getSecuritySolutionLinkProps = useCallback( + ({ deepLinkId, path, onClick }) => { + const urlState = getUrlStateQueryParams(deepLinkId); + return getLinkProps({ id: deepLinkId, path, urlState, onClick }); + }, + [getLinkProps, getUrlStateQueryParams] + ); + + return getSecuritySolutionLinkProps; +}; + +/** + * It returns the `onClick` and `href` props to use in link components + * based on the` deepLinkId` and `path` parameters. + */ +export const useSecuritySolutionLinkProps: GetSecuritySolutionLinkProps = ({ + deepLinkId, + path, + onClick, +}) => { + const getSecuritySolutionLinkProps = useGetSecuritySolutionLinkProps(); + const securitySolutionLinkProps = useMemo( + () => getSecuritySolutionLinkProps({ deepLinkId, path, onClick }), + [getSecuritySolutionLinkProps, deepLinkId, path, onClick] + ); + return securitySolutionLinkProps; +}; + +const withSecuritySolutionLinkProps = ( + WrappedComponent: React.ComponentType +): React.FC & { deepLinkId: SecurityPageName }> => + React.memo(function WithSecuritySolutionProps({ deepLinkId, ...rest }) { + const getUrlStateQueryParams = useGetUrlStateQueryParams(); + const urlState = getUrlStateQueryParams(deepLinkId); + return ; + }); + +/** + * HOC that wraps any Link component and makes it a Security solutions internal navigation Link. + */ +export const withSecuritySolutionLink = >( + WrappedComponent: React.ComponentType +) => withSecuritySolutionLinkProps(withLink(WrappedComponent)); diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/__mocks__/use_url_state_query_params.ts b/x-pack/plugins/security_solution/public/common/components/navigation/__mocks__/use_url_state_query_params.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/common/components/navigation/__mocks__/use_url_state_query_params.ts rename to x-pack/plugins/security_solution/public/common/components/navigation/__mocks__/use_url_state_query_params.tsx diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/security_side_nav/categories.ts b/x-pack/plugins/security_solution/public/common/components/navigation/security_side_nav/categories.ts index 6aeba4f593d8649..f3c1739e5bfe1fe 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/security_side_nav/categories.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/security_side_nav/categories.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { LinkCategoryType, type SeparatorLinkCategory } from '@kbn/security-solution-side-nav'; +import { LinkCategoryType, type SeparatorLinkCategory } from '@kbn/security-solution-navigation'; import { SecurityPageName } from '../../../../../common'; export const CATEGORIES: SeparatorLinkCategory[] = [ diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/security_side_nav/security_side_nav.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/security_side_nav/security_side_nav.tsx index 2b8edc760226e3a..32e02c49e20c9c3 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/security_side_nav/security_side_nav.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/security_side_nav/security_side_nav.tsx @@ -17,7 +17,7 @@ import { SecurityPageName } from '../../../../app/types'; import type { NavigationLink } from '../../../links'; import { getAncestorLinksInfo } from '../../../links'; import { useRouteSpy } from '../../../utils/route/use_route_spy'; -import { useGetSecuritySolutionLinkProps, type GetSecuritySolutionProps } from '../../links'; +import { useGetSecuritySolutionLinkProps, type GetSecuritySolutionLinkProps } from '../../links'; import { useNavLinks } from '../../../links/nav_links'; import { useShowTimeline } from '../../../utils/timeline/use_show_timeline'; import { useIsPolicySettingsBarVisible } from '../../../../management/pages/policy/view/policy_hooks'; @@ -40,7 +40,7 @@ const isGetStartedNavItem = (id: SecurityPageName) => id === SecurityPageName.la */ const formatLink = ( navLink: NavigationLink, - getSecuritySolutionLinkProps: GetSecuritySolutionProps + getSecuritySolutionLinkProps: GetSecuritySolutionLinkProps ): SolutionSideNavItem => ({ id: navLink.id, label: navLink.title, @@ -70,7 +70,7 @@ const formatLink = ( */ const formatGetStartedLink = ( navLink: NavigationLink, - getSecuritySolutionLinkProps: GetSecuritySolutionProps + getSecuritySolutionLinkProps: GetSecuritySolutionLinkProps ): SolutionSideNavItem => ({ id: navLink.id, label: navLink.title, diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.test.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.test.tsx index 752d02f1498ba92..f5bc002ac507d46 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/tab_navigation/tab_navigation.test.tsx @@ -11,28 +11,18 @@ import { navTabsHostDetails } from '../../../../explore/hosts/pages/details/nav_ import { HostsTableType } from '../../../../explore/hosts/store/model'; import { TabNavigationComponent } from './tab_navigation'; import type { TabNavigationProps } from './types'; +import { mockGetUrlForApp } from '@kbn/security-solution-navigation/mocks/context'; + +jest.mock('@kbn/security-solution-navigation/src/context'); + +mockGetUrlForApp.mockImplementation( + (appId: string, options?: { path?: string }) => `/app/${appId}${options?.path}` +); const mockUseRouteSpy = jest.fn(); jest.mock('../../../utils/route/use_route_spy', () => ({ useRouteSpy: () => mockUseRouteSpy(), })); -jest.mock('../../link_to'); -jest.mock('../../../lib/kibana/kibana_react', () => { - const originalModule = jest.requireActual('../../../lib/kibana/kibana_react'); - return { - ...originalModule, - useKibana: jest.fn().mockReturnValue({ - services: { - application: { - getUrlForApp: (appId: string, options?: { path?: string }) => - `/app/${appId}${options?.path}`, - navigateToApp: jest.fn(), - }, - }, - }), - useUiSetting$: jest.fn().mockReturnValue([]), - }; -}); const SEARCH_QUERY = '?search=test'; diff --git a/x-pack/plugins/security_solution/public/common/icons/cloud_defend.tsx b/x-pack/plugins/security_solution/public/common/icons/cloud_defend.tsx index d91e4ed2088abd5..44cd0f39250b578 100644 --- a/x-pack/plugins/security_solution/public/common/icons/cloud_defend.tsx +++ b/x-pack/plugins/security_solution/public/common/icons/cloud_defend.tsx @@ -20,19 +20,19 @@ export const IconCloudDefend: React.FC> = ({ ...props }) fillRule="evenodd" clipRule="evenodd" d="M4 22.3234L12.7273 26.7447V16.0586L4 11.6373V22.3234ZM2 22.9378C2 23.3147 2.21188 23.6595 2.54807 23.8299L13.2753 29.2644C13.9405 29.6014 14.7273 29.118 14.7273 28.3723V15.4442C14.7273 15.0673 14.5154 14.7225 14.1792 14.5521L3.45192 9.11761C2.78673 8.78062 2 9.26398 2 10.0097V22.9378Z" - fill="black" + fill="#535766" /> { return casesPermissions; }; -export type GetAppUrl = (param: { - appId?: string; - deepLinkId?: string; - path?: string; - absolute?: boolean; -}) => string; -/** - * The `getAppUrl` function returns a full URL to the provided page path by using - * kibana's `getUrlForApp()` - */ -export const useAppUrl = () => { - const { getUrlForApp } = useKibana().services.application; - - const getAppUrl = useCallback( - ({ appId = APP_UI_ID, ...options }) => getUrlForApp(appId, options), - [getUrlForApp] - ); - return { getAppUrl }; -}; - -export type NavigateTo = ( - param: { - url?: string; - appId?: string; - } & NavigateToAppOptions -) => void; -/** - * The `navigateTo` function navigates to any app using kibana's `navigateToApp()`. - * When the `{ url: string }` parameter is passed it will navigate using `navigateToUrl()`. - */ -export const useNavigateTo = () => { - const { navigateToApp, navigateToUrl } = useKibana().services.application; - - const navigateTo = useCallback( - ({ url, appId = APP_UI_ID, ...options }) => { - if (url) { - navigateToUrl(url); - } else { - navigateToApp(appId, options); - } - }, - [navigateToApp, navigateToUrl] - ); - return { navigateTo }; -}; - -/** - * Returns `navigateTo` and `getAppUrl` navigation hooks - */ -export const useNavigation = () => { - const { navigateTo } = useNavigateTo(); - const { getAppUrl } = useAppUrl(); - return { navigateTo, getAppUrl }; -}; +export const useAppUrl = useGetAppUrl; +export { useNavigateTo, useNavigation }; +export type { GetAppUrl, NavigateTo }; // Get the type for any feature capability export type FeatureCapability = Capabilities[string]; diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index 0d192428c081e8e..a71dfaf1c70bcfd 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -50,6 +50,7 @@ import { guidedOnboardingMock } from '@kbn/guided-onboarding-plugin/public/mocks import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { of } from 'rxjs'; import { UpsellingService } from '../upsellings'; +import { NavigationProvider } from '@kbn/security-solution-navigation'; const mockUiSettings: Record = { [DEFAULT_TIME_RANGE]: { from: 'now-15m', to: 'now', mode: 'quick' }, @@ -216,7 +217,11 @@ export const createKibanaContextProviderMock = () => { const services = createStartServicesMock(); return ({ children }: { children: React.ReactNode }) => - React.createElement(KibanaContextProvider, { services }, children); + React.createElement( + KibanaContextProvider, + { services }, + React.createElement(NavigationProvider, { core: services }, children) + ); }; export const getMockTheme = (partialTheme: RecursivePartial): EuiTheme => diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/constants.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/constants.ts new file mode 100644 index 000000000000000..73ea8a4dcdde44f --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/constants.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { METRIC_TYPE } from '@kbn/analytics'; + +export enum TELEMETRY_EVENT { + // Detections + SIEM_RULE_ENABLED = 'siem_rule_enabled', + SIEM_RULE_DISABLED = 'siem_rule_disabled', + CUSTOM_RULE_ENABLED = 'custom_rule_enabled', + CUSTOM_RULE_DISABLED = 'custom_rule_disabled', + // ML + SIEM_JOB_ENABLED = 'siem_job_enabled', + SIEM_JOB_DISABLED = 'siem_job_disabled', + CUSTOM_JOB_ENABLED = 'custom_job_enabled', + CUSTOM_JOB_DISABLED = 'custom_job_disabled', + JOB_ENABLE_FAILURE = 'job_enable_failure', + JOB_DISABLE_FAILURE = 'job_disable_failure', + + // Timeline + TIMELINE_OPENED = 'open_timeline', + TIMELINE_SAVED = 'timeline_saved', + TIMELINE_NAMED = 'timeline_named', + + // UI Interactions + TAB_CLICKED = 'tab_', + + // Landing pages + LANDING_CARD = 'landing_card_', + // Landing page - dashboard + DASHBOARD = 'navigate_to_dashboard', + CREATE_DASHBOARD = 'create_dashboard', + + // Breadcrumbs + BREADCRUMB = 'breadcrumb_', +} + +export enum TelemetryEventTypes { + AlertsGroupingChanged = 'Alerts Grouping Changed', + AlertsGroupingToggled = 'Alerts Grouping Toggled', + AlertsGroupingTakeAction = 'Alerts Grouping Take Action', + EntityDetailsClicked = 'Entity Details Clicked', + EntityAlertsClicked = 'Entity Alerts Clicked', + EntityRiskFiltered = 'Entity Risk Filtered', + MLJobUpdate = 'ML Job Update', + CellActionClicked = 'Cell Action Clicked', + AnomaliesCountClicked = 'Anomalies Count Clicked', +} + +export enum ML_JOB_TELEMETRY_STATUS { + started = 'started', + startError = 'start_error', + stopped = 'stopped', + stopError = 'stop_error', + moduleInstalled = 'module_installed', + installationError = 'installationError', +} diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/index.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/index.ts index 1f6fcaca3f7c8e6..5a6818c712de59e 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/index.ts @@ -5,71 +5,15 @@ * 2.0. */ -import type { UiCounterMetricType } from '@kbn/analytics'; -import { METRIC_TYPE } from '@kbn/analytics'; - -import type { SetupPlugins } from '../../../types'; import type { AlertWorkflowStatus } from '../../types'; export { telemetryMiddleware } from './middleware'; -export { METRIC_TYPE }; +export * from './constants'; export * from './telemetry_client'; export * from './telemetry_service'; +export * from './track'; export * from './types'; -type TrackFn = (type: UiCounterMetricType, event: string | string[], count?: number) => void; - -const noop = () => {}; - -let _track: TrackFn; - -export const track: TrackFn = (type, event, count) => { - try { - _track(type, event, count); - } catch (error) { - // ignore failed tracking call - } -}; - -export const initTelemetry = ( - { usageCollection }: Pick, - appId: string -) => { - _track = usageCollection?.reportUiCounter?.bind(null, appId) ?? noop; -}; - -export enum TELEMETRY_EVENT { - // Detections - SIEM_RULE_ENABLED = 'siem_rule_enabled', - SIEM_RULE_DISABLED = 'siem_rule_disabled', - CUSTOM_RULE_ENABLED = 'custom_rule_enabled', - CUSTOM_RULE_DISABLED = 'custom_rule_disabled', - // ML - SIEM_JOB_ENABLED = 'siem_job_enabled', - SIEM_JOB_DISABLED = 'siem_job_disabled', - CUSTOM_JOB_ENABLED = 'custom_job_enabled', - CUSTOM_JOB_DISABLED = 'custom_job_disabled', - JOB_ENABLE_FAILURE = 'job_enable_failure', - JOB_DISABLE_FAILURE = 'job_disable_failure', - - // Timeline - TIMELINE_OPENED = 'open_timeline', - TIMELINE_SAVED = 'timeline_saved', - TIMELINE_NAMED = 'timeline_named', - - // UI Interactions - TAB_CLICKED = 'tab_', - - // Landing pages - LANDING_CARD = 'landing_card_', - // Landing page - dashboard - DASHBOARD = 'navigate_to_dashboard', - CREATE_DASHBOARD = 'create_dashboard', - - // Breadcrumbs - BREADCRUMB = 'breadcrumb_', -} - export const getTelemetryEvent = { groupedAlertsTakeAction: ({ tableId, diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts index edd50340e873ecb..109d873ece3aaee 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts @@ -18,7 +18,7 @@ import type { ReportCellActionClickedParams, ReportAnomaliesCountClickedParams, } from './types'; -import { TelemetryEventTypes } from './types'; +import { TelemetryEventTypes } from './constants'; /** * Client which aggregate all the available telemetry tracking functions diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_events.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_events.ts index e69f90b57a1f032..dff3def5b381379 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_events.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_events.ts @@ -5,7 +5,7 @@ * 2.0. */ import type { TelemetryEvent } from './types'; -import { TelemetryEventTypes } from './types'; +import { TelemetryEventTypes } from './constants'; const alertsGroupingToggledEvent: TelemetryEvent = { eventType: TelemetryEventTypes.AlertsGroupingToggled, diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts index 0c2cd9c5082893a..557bbc96015dbd3 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_service.test.ts @@ -8,7 +8,7 @@ import { coreMock } from '@kbn/core/server/mocks'; import { telemetryEvents } from './telemetry_events'; import { TelemetryService } from './telemetry_service'; -import { TelemetryEventTypes } from './types'; +import { TelemetryEventTypes } from './constants'; describe('TelemetryService', () => { let service: TelemetryService; diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/track.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/track.ts new file mode 100644 index 000000000000000..30f58ef281840e8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/track.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 { UiCounterMetricType } from '@kbn/analytics'; +import type { SetupPlugins } from '../../../types'; + +type TrackFn = (type: UiCounterMetricType, event: string | string[], count?: number) => void; + +const noop = () => {}; + +let _track: TrackFn; + +export const track: TrackFn = (type, event, count) => { + try { + _track(type, event, count); + } catch (error) { + // ignore failed tracking call + } +}; + +export const initTelemetry = ( + { usageCollection }: Pick, + appId: string +) => { + _track = usageCollection?.reportUiCounter?.bind(null, appId) ?? noop; +}; diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/trackers.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/trackers.ts new file mode 100644 index 000000000000000..9bf2f574a572a8a --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/trackers.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { track } from './track'; +import { METRIC_TYPE, TELEMETRY_EVENT } from './constants'; + +export const trackLandingLinkClick = (pageId: string) => { + track(METRIC_TYPE.CLICK, `${TELEMETRY_EVENT.LANDING_CARD}${pageId}`); +}; diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts index f9f7c84c488edd0..d0116dc50f074ed 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts @@ -9,23 +9,12 @@ import type { RootSchema } from '@kbn/analytics-client'; import type { AnalyticsServiceSetup } from '@kbn/core/public'; import type { RiskSeverity } from '../../../../common/search_strategy'; import type { SecurityMetadata } from '../../../actions/types'; +import type { ML_JOB_TELEMETRY_STATUS, TelemetryEventTypes } from './constants'; export interface TelemetryServiceSetupParams { analytics: AnalyticsServiceSetup; } -export enum TelemetryEventTypes { - AlertsGroupingChanged = 'Alerts Grouping Changed', - AlertsGroupingToggled = 'Alerts Grouping Toggled', - AlertsGroupingTakeAction = 'Alerts Grouping Take Action', - EntityDetailsClicked = 'Entity Details Clicked', - EntityAlertsClicked = 'Entity Alerts Clicked', - EntityRiskFiltered = 'Entity Risk Filtered', - MLJobUpdate = 'ML Job Update', - CellActionClicked = 'Cell Action Clicked', - AnomaliesCountClicked = 'Anomalies Count Clicked', -} - export interface ReportAlertsGroupingChangedParams { tableId: string; groupByField: string; @@ -55,15 +44,6 @@ export interface ReportEntityRiskFilteredParams extends EntityParam { selectedSeverity: RiskSeverity; } -export enum ML_JOB_TELEMETRY_STATUS { - started = 'started', - startError = 'start_error', - stopped = 'stopped', - stopError = 'stop_error', - moduleInstalled = 'module_installed', - installationError = 'installationError', -} - export interface ReportMLJobUpdateParams { jobId: string; isElasticJob: boolean; diff --git a/x-pack/plugins/security_solution/public/common/links/links.ts b/x-pack/plugins/security_solution/public/common/links/links.ts index 87e77e5a6d4cb6c..8a4a10b97d00468 100644 --- a/x-pack/plugins/security_solution/public/common/links/links.ts +++ b/x-pack/plugins/security_solution/public/common/links/links.ts @@ -6,7 +6,7 @@ */ import { useMemo } from 'react'; import useObservable from 'react-use/lib/useObservable'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, combineLatest } from 'rxjs'; import type { SecurityPageName } from '../../../common/constants'; import { hasCapabilities } from '../lib/capabilities'; import type { @@ -19,29 +19,52 @@ import type { } from './types'; /** - * App links updater, it stores the `appLinkItems` recursive hierarchy and keeps + * Main app links updater, it stores the `mainAppLinksUpdater` recursive hierarchy and keeps * the value of the app links in sync with all application components. * It can be updated using `updateAppLinks`. - * Read it using subscription or `useAppLinks` hook. */ +const mainAppLinksUpdater$ = new BehaviorSubject([]); + +/** + * Extra App links updater, it stores the `extraAppLinksUpdater` + * that can be added externally to the app links. + * It can be updated using `updatePublicAppLinks`. + */ +const extraAppLinksUpdater$ = new BehaviorSubject([]); + +// Combines internal and external appLinks, changes on any of them will trigger a new value const appLinksUpdater$ = new BehaviorSubject([]); +export const appLinks$ = appLinksUpdater$.asObservable(); + // stores a flatten normalized appLinkItems object for internal direct id access const normalizedAppLinksUpdater$ = new BehaviorSubject({}); -// AppLinks observable -export const appLinks$ = appLinksUpdater$.asObservable(); +// Setup the appLinksUpdater$ to combine the internal and external appLinks +combineLatest([mainAppLinksUpdater$, extraAppLinksUpdater$]).subscribe( + ([mainAppLinks, extraAppLinks]) => { + appLinksUpdater$.next(Object.freeze([...mainAppLinks, ...extraAppLinks])); + } +); +// Setup the normalizedAppLinksUpdater$ to update the normalized appLinks +appLinks$.subscribe((appLinks) => { + normalizedAppLinksUpdater$.next(Object.freeze(getNormalizedLinks(appLinks))); +}); /** - * Updates the app links applying the filter by permissions + * Updates the internal app links applying the filter by permissions */ export const updateAppLinks = ( appLinksToUpdate: AppLinkItems, linksPermissions: LinksPermissions -) => { - const appLinks = processAppLinks(appLinksToUpdate, linksPermissions); - appLinksUpdater$.next(Object.freeze(appLinks)); - normalizedAppLinksUpdater$.next(Object.freeze(getNormalizedLinks(appLinks))); -}; +) => mainAppLinksUpdater$.next(Object.freeze(processAppLinks(appLinksToUpdate, linksPermissions))); + +/** + * Updates the app links applying the filter by permissions + */ +export const updateExtraAppLinks = ( + appLinksToUpdate: AppLinkItems, + linksPermissions: LinksPermissions +) => extraAppLinksUpdater$.next(Object.freeze(processAppLinks(appLinksToUpdate, linksPermissions))); /** * Hook to get the app links updated value @@ -134,11 +157,11 @@ export const getLinksWithHiddenTimeline = (): LinkInfo[] => { /** * Creates the `NormalizedLinks` structure from a `LinkItem` array */ -const getNormalizedLinks = ( +function getNormalizedLinks( currentLinks: AppLinkItems, parentId?: SecurityPageName -): NormalizedLinks => - currentLinks.reduce((normalized, { links, ...currentLink }) => { +): NormalizedLinks { + return currentLinks.reduce((normalized, { links, ...currentLink }) => { normalized[currentLink.id] = { ...currentLink, parentId, @@ -148,6 +171,7 @@ const getNormalizedLinks = ( } return normalized; }, {}); +} const getNormalizedLink = (id: SecurityPageName): Readonly | undefined => normalizedAppLinksUpdater$.getValue()[id]; diff --git a/x-pack/plugins/security_solution/public/common/links/types.ts b/x-pack/plugins/security_solution/public/common/links/types.ts index 2982edbf8f15700..f83e5ad6f77971e 100644 --- a/x-pack/plugins/security_solution/public/common/links/types.ts +++ b/x-pack/plugins/security_solution/public/common/links/types.ts @@ -9,11 +9,12 @@ import type { Capabilities } from '@kbn/core/types'; import type { ILicense, LicenseType } from '@kbn/licensing-plugin/common/types'; import type { IconType } from '@elastic/eui'; import type { - LinkCategory as BaseLinkCategory, - LinkCategories as BaseLinkCategories, -} from '@kbn/security-solution-side-nav'; + SecurityPageName, + NavigationLink as GenericNavigationLink, + LinkCategory as GenericLinkCategory, + LinkCategories as GenericLinkCategories, +} from '@kbn/security-solution-navigation'; import type { ExperimentalFeatures } from '../../../common/experimental_features'; -import type { SecurityPageName } from '../../../common/constants'; import type { UpsellingService } from '../lib/upsellings'; import type { RequiredCapabilities } from '../lib/capabilities'; @@ -27,9 +28,6 @@ export interface LinksPermissions { license?: ILicense; } -export type LinkCategory = BaseLinkCategory; -export type LinkCategories = BaseLinkCategories; - export interface LinkItem { /** * Capabilities strings (using object dot notation) to enable the link. @@ -143,20 +141,6 @@ export type LinkInfo = Omit; export type NormalizedLink = LinkInfo & { parentId?: SecurityPageName }; export type NormalizedLinks = Partial>; -export interface NavigationLink { - categories?: LinkCategories; - description?: string; - disabled?: boolean; - id: SecurityPageName; - landingIcon?: IconType; - landingImage?: string; - links?: NavigationLink[]; - title: string; - sideNavIcon?: IconType; - skipUrlState?: boolean; - unauthorized?: boolean; - isBeta?: boolean; - betaOptions?: { - text: string; - }; -} +export type NavigationLink = GenericNavigationLink; +export type LinkCategory = GenericLinkCategory; +export type LinkCategories = GenericLinkCategories; diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx index d8e572a7bb119fa..3c0e4620a4000dc 100644 --- a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx @@ -23,6 +23,7 @@ import type { } from '@testing-library/react-hooks/src/types/react'; import type { UseBaseQueryResult } from '@tanstack/react-query'; import ReactDOM from 'react-dom'; +import { NavigationProvider } from '@kbn/security-solution-navigation'; import type { AppLinkItems } from '../../links/types'; import { ExperimentalFeaturesService } from '../../experimental_features_service'; import { applyIntersectionObserverMock } from '../intersection_observer_mock'; @@ -240,7 +241,9 @@ export const createAppRootMockRenderer = (): AppContextTestRender => { - {children} + + {children} + diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_root_provider.tsx b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_root_provider.tsx index 1e5ecad2d022381..799485574a4eb72 100644 --- a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_root_provider.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_root_provider.tsx @@ -16,6 +16,7 @@ import type { Store } from 'redux'; import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import type { CoreStart } from '@kbn/core/public'; +import { NavigationProvider } from '@kbn/security-solution-navigation'; import { MockAssistantProvider } from '../mock_assistant_provider'; import { RouteCapture } from '../../components/endpoint/route_capture'; import type { StartPlugins } from '../../../types'; @@ -29,35 +30,30 @@ export const AppRootProvider = memo<{ coreStart: CoreStart; depsStart: Pick; children: ReactNode | ReactNode[]; -}>( - ({ - store, - history, - coreStart: { http, notifications, uiSettings, application }, - depsStart: { data }, - children, - }) => { - const isDarkMode = useObservable(uiSettings.get$('theme:darkMode')); - const services = useMemo( - () => ({ http, notifications, application, data }), - [application, data, http, notifications] - ); - return ( - - - - - +}>(({ store, history, coreStart, depsStart: { data }, children }) => { + const { http, notifications, uiSettings, application } = coreStart; + const isDarkMode = useObservable(uiSettings.get$('theme:darkMode')); + const services = useMemo( + () => ({ http, notifications, application, data }), + [application, data, http, notifications] + ); + return ( + + + + + + {children} - - - - - - ); - } -); + + + + + + + ); +}); AppRootProvider.displayName = 'AppRootProvider'; diff --git a/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx b/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx index 20cf908b2d555da..1026c69da8d8e55 100644 --- a/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/hooks/use_security_dashboards_table.test.tsx @@ -16,7 +16,8 @@ import { useSecurityDashboardsTableColumns, useSecurityDashboardsTableItems, } from './use_security_dashboards_table'; -import * as telemetry from '../../common/lib/telemetry'; +import { METRIC_TYPE, TELEMETRY_EVENT } from '../../common/lib/telemetry/constants'; +import * as telemetry from '../../common/lib/telemetry/track'; import { SecurityPageName } from '../../../common/constants'; import * as linkTo from '../../common/components/link_to'; import { getDashboardsByTagIds } from '../../common/containers/dashboards/api'; @@ -175,10 +176,7 @@ describe('Security Dashboards Table hooks', () => { ); result.getByText(mockReturnDashboardTitle).click(); - expect(spyTrack).toHaveBeenCalledWith( - telemetry.METRIC_TYPE.CLICK, - telemetry.TELEMETRY_EVENT.DASHBOARD - ); + expect(spyTrack).toHaveBeenCalledWith(METRIC_TYPE.CLICK, TELEMETRY_EVENT.DASHBOARD); }); it('should land on SecuritySolution dashboard view page when dashboard title clicked', async () => { diff --git a/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.test.tsx b/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.test.tsx index 357cf5d21670b38..9b43945ed6a8da4 100644 --- a/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.test.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.test.tsx @@ -11,12 +11,13 @@ import { SecurityPageName } from '../../../app/types'; import { TestProviders } from '../../../common/mock'; import { DashboardsLandingPage } from '.'; import { useCapabilities } from '../../../common/lib/kibana'; -import * as telemetry from '../../../common/lib/telemetry'; -import { DashboardListingTable } from '@kbn/dashboard-plugin/public'; +import { METRIC_TYPE, TELEMETRY_EVENT } from '../../../common/lib/telemetry/constants'; +import * as telemetry from '../../../common/lib/telemetry/track'; import { MOCK_TAG_NAME } from '../../../common/containers/tags/__mocks__/api'; import { DashboardContextProvider } from '../../context/dashboard_context'; import { act } from 'react-dom/test-utils'; import type { NavigationLink } from '../../../common/links/types'; +import { DashboardListingTable } from '@kbn/dashboard-plugin/public'; jest.mock('../../../common/containers/tags/api'); jest.mock('../../../common/lib/kibana'); @@ -188,10 +189,7 @@ describe('Dashboards landing', () => { it('should send telemetry', async () => { await renderDashboardLanding(); screen.getByTestId('createDashboardButton').click(); - expect(spyTrack).toHaveBeenCalledWith( - telemetry.METRIC_TYPE.CLICK, - telemetry.TELEMETRY_EVENT.CREATE_DASHBOARD - ); + expect(spyTrack).toHaveBeenCalledWith(METRIC_TYPE.CLICK, TELEMETRY_EVENT.CREATE_DASHBOARD); }); }); }); diff --git a/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.tsx b/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.tsx index 6da70442a1e3f2c..fa2150d841ef76c 100644 --- a/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.tsx +++ b/x-pack/plugins/security_solution/public/dashboards/pages/landing_page/index.tsx @@ -16,9 +16,9 @@ import { import React, { useCallback, useMemo } from 'react'; import type { DashboardCapabilities } from '@kbn/dashboard-plugin/common/types'; import { DashboardListingTable, LEGACY_DASHBOARD_APP_ID } from '@kbn/dashboard-plugin/public'; +import { LandingLinksImageCards } from '@kbn/security-solution-navigation/landing_links'; import { SecuritySolutionPageWrapper } from '../../../common/components/page_wrapper'; import { SpyRoute } from '../../../common/utils/route/spy_routes'; -import { LandingImageCards } from '../../../common/components/landing_links/landing_links_images'; import { SecurityPageName } from '../../../../common/constants'; import { useCapabilities, useNavigateTo } from '../../../common/lib/kibana'; import { useRootNavLink } from '../../../common/links/nav_links'; @@ -29,6 +29,8 @@ import { METRIC_TYPE, TELEMETRY_EVENT, track } from '../../../common/lib/telemet import { DASHBOARDS_PAGE_TITLE } from '../translations'; import { useCreateSecurityDashboardLink } from '../../hooks/use_create_security_dashboard_link'; import { useGetSecuritySolutionUrl } from '../../../common/components/link_to'; +import { useGlobalQueryString } from '../../../common/utils/global_query_string'; +import { trackLandingLinkClick } from '../../../common/lib/telemetry/trackers'; import type { TagReference } from '../../context/dashboard_context'; import { useSecurityTags } from '../../context/dashboard_context'; @@ -80,7 +82,8 @@ const Header: React.FC<{ canCreateDashboard: boolean }> = ({ canCreateDashboard }; export const DashboardsLandingPage = () => { - const dashboardLinks = useRootNavLink(SecurityPageName.dashboards)?.links ?? []; + const { links = [] } = useRootNavLink(SecurityPageName.dashboards) ?? {}; + const urlState = useGlobalQueryString(); const { show: canReadDashboard, createNew: canCreateDashboard } = useCapabilities(LEGACY_DASHBOARD_APP_ID); const { navigateTo } = useNavigateTo(); @@ -122,7 +125,11 @@ export const DashboardsLandingPage = () => {

{i18n.DASHBOARDS_PAGE_SECTION_DEFAULT}

- + {canReadDashboard && securityTagsExist && initialFilter ? ( diff --git a/x-pack/plugins/security_solution/public/explore/landing.tsx b/x-pack/plugins/security_solution/public/explore/landing.tsx index a861f7a7ec0f3a2..6c227b390fc20b2 100644 --- a/x-pack/plugins/security_solution/public/explore/landing.tsx +++ b/x-pack/plugins/security_solution/public/explore/landing.tsx @@ -6,24 +6,27 @@ */ import React from 'react'; import { i18n } from '@kbn/i18n'; +import { LandingLinksImages } from '@kbn/security-solution-navigation/landing_links'; import { SecurityPageName } from '../app/types'; import { HeaderPage } from '../common/components/header_page'; import { useRootNavLink } from '../common/links/nav_links'; import { SecuritySolutionPageWrapper } from '../common/components/page_wrapper'; import { SpyRoute } from '../common/utils/route/spy_routes'; -import { LandingLinksImages } from '../common/components/landing_links/landing_links_images'; +import { trackLandingLinkClick } from '../common/lib/telemetry/trackers'; +import { useGlobalQueryString } from '../common/utils/global_query_string'; const EXPLORE_PAGE_TITLE = i18n.translate('xpack.securitySolution.explore.landing.pageTitle', { defaultMessage: 'Explore', }); export const ExploreLandingPage = () => { - const exploreLinks = useRootNavLink(SecurityPageName.exploreLanding)?.links ?? []; + const { links = [] } = useRootNavLink(SecurityPageName.exploreLanding) ?? {}; + const urlState = useGlobalQueryString(); return ( - + ); diff --git a/x-pack/plugins/security_solution/public/explore/network/components/ip/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/components/ip/index.test.tsx index eb9d92b4f0264a6..d2246541dbb2e84 100644 --- a/x-pack/plugins/security_solution/public/explore/network/components/ip/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/components/ip/index.test.tsx @@ -24,7 +24,7 @@ jest.mock('@elastic/eui', () => { }; }); -jest.mock('../../../../common/components/link_to'); +jest.mock('../../../../common/components/links/link_props'); describe('Port', () => { const mount = useMountAppended(); diff --git a/x-pack/plugins/security_solution/public/helpers.test.tsx b/x-pack/plugins/security_solution/public/helpers.test.tsx index 251b83f1293f0a0..a305434a1ff11e1 100644 --- a/x-pack/plugins/security_solution/public/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/helpers.test.tsx @@ -14,7 +14,6 @@ import { parseRoute, isSubPluginAvailable, getSubPluginRoutesByCapabilities, - RedirectRoute, getField, } from './helpers'; import type { StartedSubPlugins } from './types'; @@ -210,92 +209,6 @@ describe('#isSubPluginAvailable', () => { }); }); -describe('RedirectRoute', () => { - it('RedirectRoute should redirect to overview page when siem and case privileges are all', () => { - const mockCapabilities = { - [SERVER_APP_ID]: { show: true, crud: true }, - [CASES_FEATURE_ID]: allCasesCapabilities(), - } as unknown as Capabilities; - expect(shallow()).toMatchInlineSnapshot(` - - `); - }); - - it('RedirectRoute should redirect to overview page when siem and case privileges are read', () => { - const mockCapabilities = { - [SERVER_APP_ID]: { show: true, crud: false }, - [CASES_FEATURE_ID]: readCasesCapabilities(), - } as unknown as Capabilities; - expect(shallow()).toMatchInlineSnapshot(` - - `); - }); - - it('RedirectRoute should redirect to overview page when siem and case privileges are off', () => { - const mockCapabilities = { - [SERVER_APP_ID]: { show: false, crud: false }, - [CASES_FEATURE_ID]: noCasesCapabilities(), - } as unknown as Capabilities; - expect(shallow()).toMatchInlineSnapshot(` - - `); - }); - - it('RedirectRoute should redirect to overview page when siem privilege is read and case privilege is all', () => { - const mockCapabilities = { - [SERVER_APP_ID]: { show: true, crud: false }, - [CASES_FEATURE_ID]: allCasesCapabilities(), - } as unknown as Capabilities; - expect(shallow()).toMatchInlineSnapshot(` - - `); - }); - - it('RedirectRoute should redirect to overview page when siem privilege is read and case privilege is read', () => { - const mockCapabilities = { - [SERVER_APP_ID]: { show: true, crud: false }, - [CASES_FEATURE_ID]: allCasesCapabilities(), - } as unknown as Capabilities; - expect(shallow()).toMatchInlineSnapshot(` - - `); - }); - - it('RedirectRoute should redirect to cases page when siem privilege is none and case privilege is read', () => { - const mockCapabilities = { - [SERVER_APP_ID]: { show: false, crud: false }, - [CASES_FEATURE_ID]: readCasesCapabilities(), - } as unknown as Capabilities; - expect(shallow()).toMatchInlineSnapshot(` - - `); - }); - - it('RedirectRoute should redirect to cases page when siem privilege is none and case privilege is all', () => { - const mockCapabilities = { - [SERVER_APP_ID]: { show: false, crud: false }, - [CASES_FEATURE_ID]: allCasesCapabilities(), - } as unknown as Capabilities; - expect(shallow()).toMatchInlineSnapshot(` - - `); - }); -}); - describe('public helpers getField', () => { it('should return the same value for signal.rule fields as for kibana.alert.rule fields', () => { const signalRuleName = getField(mockEcsDataWithAlert, 'signal.rule.name'); diff --git a/x-pack/plugins/security_solution/public/helpers.tsx b/x-pack/plugins/security_solution/public/helpers.tsx index 2dffcdc87beb04a..5a6e2c2c5108ded 100644 --- a/x-pack/plugins/security_solution/public/helpers.tsx +++ b/x-pack/plugins/security_solution/public/helpers.tsx @@ -9,7 +9,7 @@ import { ALERT_RULE_NAME, ALERT_RULE_PARAMETERS, ALERT_RULE_UUID } from '@kbn/ru import { get, has, isEmpty } from 'lodash/fp'; import React from 'react'; import type { RouteProps } from 'react-router-dom'; -import { matchPath, Redirect } from 'react-router-dom'; +import { matchPath } from 'react-router-dom'; import type { Capabilities, CoreStart } from '@kbn/core/public'; import type { DocLinks } from '@kbn/doc-links'; @@ -21,7 +21,6 @@ import { CASES_FEATURE_ID, CASES_PATH, EXCEPTIONS_PATH, - LANDING_PATH, RULES_PATH, SERVER_APP_ID, THREAT_INTELLIGENCE_PATH, @@ -198,15 +197,12 @@ export const getSubPluginRoutesByCapabilities = ( capabilities: Capabilities, services: StartServices ): RouteProps[] => { - return [ - ...Object.entries(subPlugins).reduce((acc, [key, value]) => { - if (isSubPluginAvailable(key, capabilities)) { - return [...acc, ...value.routes]; - } + return Object.entries(subPlugins).reduce((acc, [key, value]) => { + if (isSubPluginAvailable(key, capabilities)) { + acc.push(...value.routes); + } else { const docLinkSelector = (docLinks: DocLinks) => docLinks.siem.privileges; - - return [ - ...acc, + acc.push( ...value.routes.map((route: RouteProps) => ({ path: route.path, component: () => { @@ -216,14 +212,11 @@ export const getSubPluginRoutesByCapabilities = ( } return ; }, - })), - ]; - }, []), - { - path: '', - component: () => , - }, - ]; + })) + ); + } + return acc; + }, []); }; export const isSubPluginAvailable = (pluginKey: string, capabilities: Capabilities): boolean => { @@ -233,19 +226,6 @@ export const isSubPluginAvailable = (pluginKey: string, capabilities: Capabiliti return capabilities[SERVER_APP_ID].show === true; }; -export const RedirectRoute = React.memo<{ capabilities: Capabilities }>(({ capabilities }) => { - const overviewAvailable = isSubPluginAvailable('overview', capabilities); - const casesAvailable = isSubPluginAvailable(CASES_SUB_PLUGIN_KEY, capabilities); - if (overviewAvailable) { - return ; - } - if (casesAvailable) { - return ; - } - return ; -}); -RedirectRoute.displayName = 'RedirectRoute'; - const siemSignalsFieldMappings: Record = { [ALERT_RULE_UUID]: 'signal.rule.id', [ALERT_RULE_NAME]: 'signal.rule.name', diff --git a/x-pack/plugins/security_solution/public/index.ts b/x-pack/plugins/security_solution/public/index.ts index 8d0203e32fb0f13..1ba754a747b0700 100644 --- a/x-pack/plugins/security_solution/public/index.ts +++ b/x-pack/plugins/security_solution/public/index.ts @@ -9,7 +9,7 @@ import type { PluginInitializerContext } from '@kbn/core/public'; import { Plugin } from './plugin'; import type { PluginSetup, PluginStart } from './types'; export type { TimelineModel } from './timelines/store/timeline/model'; -export type { NavigationLink } from './common/links'; +export type { LinkItem } from './common/links'; export type { UpsellingService, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts index 6f6a4934dab0e91..ca1b0dfb56fea0f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { firstValueFrom } from 'rxjs'; import type { CoreStart, HttpSetup } from '@kbn/core/public'; import type { Store } from 'redux'; import { applyMiddleware, createStore } from 'redux'; @@ -52,13 +51,16 @@ jest.mock('../../../services/policies/ingest', () => ({ })); jest.mock('../../../../common/lib/kibana'); -jest.mock('rxjs'); +const mockFirstValueFrom = jest.fn(); +jest.mock('rxjs', () => ({ + ...jest.requireActual('rxjs'), + firstValueFrom: () => mockFirstValueFrom(), +})); type EndpointListStore = Store, Immutable>; describe('endpoint list middleware', () => { const getKibanaServicesMock = KibanaServices.get as jest.Mock; - const firstValueFromMock = firstValueFrom as jest.Mock; let fakeCoreStart: jest.Mocked; let depsStart: DepsStartMock; let fakeHttpServices: jest.Mocked; @@ -119,7 +121,7 @@ describe('endpoint list middleware', () => { }); it('handles `appRequestedEndpointList`', async () => { - firstValueFromMock.mockResolvedValue({ indexFields: [] }); + mockFirstValueFrom.mockResolvedValue({ indexFields: [] }); endpointPageHttpMock(fakeHttpServices); const apiResponse = getEndpointListApiResponse(); fakeHttpServices.get.mockResolvedValue(apiResponse); diff --git a/x-pack/plugins/security_solution/public/management/pages/landing.tsx b/x-pack/plugins/security_solution/public/management/pages/landing.tsx index cbfc4e4b087a0f1..a6030f0f94ec2d9 100644 --- a/x-pack/plugins/security_solution/public/management/pages/landing.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/landing.tsx @@ -6,21 +6,34 @@ */ import React from 'react'; import { i18n } from '@kbn/i18n'; +import { LandingLinksIconsCategories } from '@kbn/security-solution-navigation/landing_links'; import { SecurityPageName } from '../../app/types'; import { HeaderPage } from '../../common/components/header_page'; import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; import { SpyRoute } from '../../common/utils/route/spy_routes'; -import { LandingLinksIconsCategories } from '../../common/components/landing_links/landing_links_icons_categories'; +import { useRootNavLink } from '../../common/links/nav_links'; +import { useGlobalQueryString } from '../../common/utils/global_query_string'; +import { trackLandingLinkClick } from '../../common/lib/telemetry/trackers'; const PAGE_TITLE = i18n.translate('xpack.securitySolution.management.landing.settingsTitle', { defaultMessage: 'Settings', }); -export const ManageLandingPage = () => ( - - - - - -); +export const ManageLandingPage = () => { + const { links = [], categories = [] } = useRootNavLink(SecurityPageName.administration) ?? {}; + const urlState = useGlobalQueryString(); + + return ( + + + + + + ); +}; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/render_context_providers.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/render_context_providers.tsx index ee0643ca2883ac5..003a3debf852a64 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/render_context_providers.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/components/with_security_context/render_context_providers.tsx @@ -9,6 +9,7 @@ import type { PropsWithChildren } from 'react'; import React, { memo } from 'react'; import { Provider as ReduxStoreProvider } from 'react-redux'; import type { Store } from 'redux'; +import { NavigationProvider } from '@kbn/security-solution-navigation'; import { UserPrivilegesProvider } from '../../../../../../../common/components/user_privileges/user_privileges_context'; import type { SecuritySolutionQueryClient } from '../../../../../../../common/containers/query_client/query_client_provider'; import { ReactQueryClientProvider } from '../../../../../../../common/containers/query_client/query_client_provider'; @@ -25,15 +26,18 @@ export type RenderContextProvidersProps = PropsWithChildren<{ export const RenderContextProviders = memo( ({ store, depsStart, queryClient, children }) => { + const services = useKibana().services; const { application: { capabilities }, - } = useKibana().services; + } = services; return ( - {children} + + {children} + diff --git a/x-pack/plugins/security_solution/public/mocks.ts b/x-pack/plugins/security_solution/public/mocks.ts index 0a1072f5fd22f10..c255bb6383ce52a 100644 --- a/x-pack/plugins/security_solution/public/mocks.ts +++ b/x-pack/plugins/security_solution/public/mocks.ts @@ -8,18 +8,23 @@ import { BehaviorSubject } from 'rxjs'; import type { BreadcrumbsNav } from './common/breadcrumbs'; import type { NavigationLink } from './common/links/types'; +import { UpsellingService } from './common/lib/upsellings'; +import type { PluginStart, PluginSetup } from './types'; -const setupMock = () => ({ +const setupMock = (): PluginSetup => ({ resolver: jest.fn(), + upselling: new UpsellingService(), }); -const startMock = () => ({ +const startMock = (): PluginStart => ({ getNavLinks$: jest.fn(() => new BehaviorSubject([])), setIsSidebarEnabled: jest.fn(), setGetStartedPage: jest.fn(), getBreadcrumbsNav$: jest.fn( () => new BehaviorSubject({ leading: [], trailing: [] }) ), + setExtraAppLinks: jest.fn(), + setExtraRoutes: jest.fn(), }); export const securitySolutionMock = { diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index e52273785ea1ba0..9b8b440f6ed25c2 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { Subject } from 'rxjs'; +import { combineLatest, Subject } from 'rxjs'; import type * as H from 'history'; import type { AppMountParameters, @@ -36,7 +36,7 @@ import { SOLUTION_NAME } from './common/translations'; import { APP_ID, APP_UI_ID, APP_PATH, APP_ICON_SOLUTION } from '../common/constants'; -import { updateAppLinks, type LinksPermissions } from './common/links'; +import { updateAppLinks, updateExtraAppLinks, type LinksPermissions } from './common/links'; import { registerDeepLinksUpdater } from './common/links/deep_links'; import { licenseService } from './common/hooks/use_license'; import type { SecuritySolutionUiConfigType } from './common/types'; @@ -503,21 +503,22 @@ export class Plugin implements IPlugin { const linksPermissions: LinksPermissions = { - experimentalFeatures: this.experimentalFeatures, - upselling, - capabilities: core.application.capabilities, + ...baseLinksPermissions, + ...(license.type != null && { license }), }; - if (license.type !== undefined) { - linksPermissions.license = license; - } - // set initial links to not block rendering updateAppLinks(links, linksPermissions); @@ -525,5 +526,12 @@ export class Plugin implements IPlugin { + updateExtraAppLinks(extraAppLinks, { + ...baseLinksPermissions, + ...(license.type != null && { license }), + }); + }); } } diff --git a/x-pack/plugins/security_solution/public/plugin_contract.ts b/x-pack/plugins/security_solution/public/plugin_contract.ts index 583424509e13181..06fb9f2938498a9 100644 --- a/x-pack/plugins/security_solution/public/plugin_contract.ts +++ b/x-pack/plugins/security_solution/public/plugin_contract.ts @@ -6,8 +6,10 @@ */ import { BehaviorSubject } from 'rxjs'; +import type { RouteProps } from 'react-router-dom'; import { UpsellingService } from './common/lib/upsellings'; import type { ContractStartServices, PluginSetup, PluginStart } from './types'; +import type { AppLinkItems } from './common/links'; import { navLinks$ } from './common/links/nav_links'; import { breadcrumbsNav$ } from './common/breadcrumbs'; @@ -15,8 +17,12 @@ export class PluginContract { public isSidebarEnabled$: BehaviorSubject; public getStartedComponent$: BehaviorSubject; public upsellingService: UpsellingService; + public extraAppLinks$: BehaviorSubject; + public extraRoutes$: BehaviorSubject; constructor() { + this.extraAppLinks$ = new BehaviorSubject([]); + this.extraRoutes$ = new BehaviorSubject([]); this.isSidebarEnabled$ = new BehaviorSubject(true); this.getStartedComponent$ = new BehaviorSubject(null); this.upsellingService = new UpsellingService(); @@ -24,6 +30,7 @@ export class PluginContract { public getStartServices(): ContractStartServices { return { + extraRoutes$: this.extraRoutes$.asObservable(), isSidebarEnabled$: this.isSidebarEnabled$.asObservable(), getStartedComponent$: this.getStartedComponent$.asObservable(), upselling: this.upsellingService, @@ -40,6 +47,8 @@ export class PluginContract { public getStartContract(): PluginStart { return { getNavLinks$: () => navLinks$, + setExtraAppLinks: (extraAppLinks) => this.extraAppLinks$.next(extraAppLinks), + setExtraRoutes: (extraRoutes) => this.extraRoutes$.next(extraRoutes), setIsSidebarEnabled: (isSidebarEnabled: boolean) => this.isSidebarEnabled$.next(isSidebarEnabled), setGetStartedPage: (getStartedComponent) => { diff --git a/x-pack/plugins/security_solution/public/rules/landing.tsx b/x-pack/plugins/security_solution/public/rules/landing.tsx index 951f66a06351687..aaf28d48d0bd732 100644 --- a/x-pack/plugins/security_solution/public/rules/landing.tsx +++ b/x-pack/plugins/security_solution/public/rules/landing.tsx @@ -8,13 +8,16 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { LandingLinksIconsCategories } from '@kbn/security-solution-navigation/landing_links'; import { SecurityPageName } from '../../common'; import { PluginTemplateWrapper } from '../common/components/plugin_template_wrapper'; import { SecuritySolutionPageWrapper } from '../common/components/page_wrapper'; import { SpyRoute } from '../common/utils/route/spy_routes'; -import { LandingLinksIconsCategories } from '../common/components/landing_links/landing_links_icons_categories'; import { Title } from '../common/components/header_page/title'; import { SecuritySolutionLinkButton } from '../common/components/links'; +import { useRootNavLink } from '../common/links/nav_links'; +import { useGlobalQueryString } from '../common/utils/global_query_string'; +import { trackLandingLinkClick } from '../common/lib/telemetry/trackers'; const RULES_PAGE_TITLE = i18n.translate('xpack.securitySolution.rules.landing.pageTitle', { defaultMessage: 'Rules', @@ -37,15 +40,25 @@ const RulesLandingHeader: React.FC = () => ( ); -export const RulesLandingPage = () => ( - - - - - - - - - - -); +export const RulesLandingPage = () => { + const { links = [], categories = [] } = useRootNavLink(SecurityPageName.rulesLanding) ?? {}; + const urlState = useGlobalQueryString(); + + return ( + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/security_solution/public/rules/links.ts b/x-pack/plugins/security_solution/public/rules/links.ts index 58333e46dc9bfe2..d466a847f8defc6 100644 --- a/x-pack/plugins/security_solution/public/rules/links.ts +++ b/x-pack/plugins/security_solution/public/rules/links.ts @@ -25,6 +25,7 @@ export const links: LinkItem = { title: RULES, path: RULES_LANDING_PATH, hideTimeline: true, + skipUrlState: true, links: [ { id: SecurityPageName.rules, diff --git a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx index 47ea68dcf75a900..2c20b0bc20facc0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx @@ -29,20 +29,14 @@ import { mockData } from '../../../explore/network/components/details/mock'; import type { AutonomousSystem } from '../../../../common/search_strategy'; import { FlowTarget } from '../../../../common/search_strategy'; import type { HostEcs } from '@kbn/securitysolution-ecs'; +import { mockGetUrlForApp } from '@kbn/security-solution-navigation/mocks/context'; jest.mock('../../../common/lib/kibana'); -jest.mock('../../../common/lib/kibana/kibana_react', () => { - return { - useKibana: () => ({ - services: { - application: { - getUrlForApp: (appId: string, options?: { path?: string; deepLinkId?: boolean }) => - `${appId}/${options?.deepLinkId ?? ''}${options?.path ?? ''}`, - }, - }, - }), - }; -}); +jest.mock('@kbn/security-solution-navigation/src/context'); +mockGetUrlForApp.mockImplementation( + (appId: string, options?: { path?: string; deepLinkId?: boolean }) => + `${appId}/${options?.deepLinkId ?? ''}${options?.path ?? ''}` +); jest.mock('../../../common/hooks/use_get_field_spec'); diff --git a/x-pack/plugins/security_solution/public/timelines/components/netflow/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/netflow/index.test.tsx index 4e2286789da36d7..47036a260e4746d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/netflow/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/netflow/index.test.tsx @@ -134,7 +134,7 @@ const getNetflowInstance = () => ( /> ); -jest.mock('../../../common/components/link_to'); +jest.mock('../../../common/components/links/link_props'); describe('Netflow', () => { test('renders correctly against snapshot', () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/netflow_row_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/netflow_row_renderer.test.tsx index a65e46a844f9618..65defb52de7829d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/netflow_row_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/netflow_row_renderer.test.tsx @@ -25,8 +25,7 @@ export const justIdAndTimestamp: Ecs = { }; jest.mock('../../../../../../common/lib/kibana'); - -jest.mock('../../../../../../common/components/link_to'); +jest.mock('../../../../../../common/components/links/link_props'); describe('netflowRowRenderer', () => { test('renders correctly against snapshot', () => { diff --git a/x-pack/plugins/security_solution/public/types.ts b/x-pack/plugins/security_solution/public/types.ts index ffcc1feb8c7db66..4718c257cec0708 100644 --- a/x-pack/plugins/security_solution/public/types.ts +++ b/x-pack/plugins/security_solution/public/types.ts @@ -50,6 +50,7 @@ import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/ import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; +import type { RouteProps } from 'react-router-dom'; import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { NavigationPublicPluginStart } from '@kbn/navigation-plugin/public'; import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; @@ -68,7 +69,7 @@ import type { CloudDefend } from './cloud_defend'; import type { ThreatIntelligence } from './threat_intelligence'; import type { SecuritySolutionTemplateWrapper } from './app/home/template_wrapper'; import type { Explore } from './explore'; -import type { NavigationLink } from './common/links'; +import type { AppLinkItems, NavigationLink } from './common/links'; import type { EntityAnalytics } from './entity_analytics'; import type { TelemetryClientStart } from './common/lib/telemetry'; @@ -137,6 +138,7 @@ export interface StartPluginsDependencies extends StartPlugins { } export interface ContractStartServices { + extraRoutes$: Observable; isSidebarEnabled$: Observable; getStartedComponent$: Observable; upselling: UpsellingService; @@ -172,6 +174,8 @@ export interface PluginSetup { export interface PluginStart { getNavLinks$: () => Observable; + setExtraAppLinks: (extraAppLinks: AppLinkItems) => void; + setExtraRoutes: (extraRoutes: RouteProps[]) => void; setIsSidebarEnabled: (isSidebarEnabled: boolean) => void; setGetStartedPage: (getStartedComponent: React.ComponentType) => void; getBreadcrumbsNav$: () => Observable; diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index 3828a6839cd6c06..6ac3e400a6541f3 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -161,9 +161,10 @@ "@kbn/field-formats-plugin", "@kbn/dev-proc-runner", "@kbn/cloud-chat-plugin", + "@kbn/alerts-ui-shared", + "@kbn/security-solution-navigation", "@kbn/discover-plugin", - "@kbn/navigation-plugin", "@kbn/data-view-editor-plugin", - "@kbn/alerts-ui-shared" + "@kbn/navigation-plugin", ] } diff --git a/x-pack/plugins/security_solution_serverless/common/pli/pli_features.test.ts b/x-pack/plugins/security_solution_serverless/common/pli/pli_features.test.ts index 3358ee69a42508f..d48141bf58aca09 100644 --- a/x-pack/plugins/security_solution_serverless/common/pli/pli_features.test.ts +++ b/x-pack/plugins/security_solution_serverless/common/pli/pli_features.test.ts @@ -41,32 +41,6 @@ describe('getProductAppFeatures', () => { expect(appFeatureKeys).toEqual(['foo', 'baz']); }); - it('should return the union of all enabled PLIs features without duplicates', () => { - // @ts-ignore reassigning readonly value for testing - pliConfig.PLI_APP_FEATURES = { - security: { - essentials: ['foo'], - complete: ['baz'], - }, - endpoint: { - essentials: ['bar', 'repeated'], - complete: ['qux', 'quux'], - }, - cloud: { - essentials: ['corge', 'garply', 'repeated'], - complete: ['grault'], - }, - }; - - const appFeatureKeys = getProductAppFeatures([ - { product_line: ProductLine.security, product_tier: ProductTier.essentials }, - { product_line: ProductLine.endpoint, product_tier: ProductTier.complete }, - { product_line: ProductLine.cloud, product_tier: ProductTier.essentials }, - ]); - - expect(appFeatureKeys).toEqual(['foo', 'bar', 'repeated', 'qux', 'quux', 'corge', 'garply']); - }); - it('returns an empty object if no PLIs are enabled', () => { expect(getProductAppFeatures([])).toEqual([]); }); diff --git a/x-pack/plugins/security_solution_serverless/common/pli/pli_features.ts b/x-pack/plugins/security_solution_serverless/common/pli/pli_features.ts index e4c01207ed3811a..5db2945f512e895 100644 --- a/x-pack/plugins/security_solution_serverless/common/pli/pli_features.ts +++ b/x-pack/plugins/security_solution_serverless/common/pli/pli_features.ts @@ -6,8 +6,8 @@ */ import type { AppFeatureKeys } from '@kbn/security-solution-plugin/common'; -import uniq from 'lodash/fp/uniq'; import type { SecurityProductTypes } from '../config'; +import { ProductTier } from '../product'; import { PLI_APP_FEATURES } from './pli_config'; /** @@ -16,14 +16,13 @@ import { PLI_APP_FEATURES } from './pli_config'; export const getProductAppFeatures = (productTypes: SecurityProductTypes): AppFeatureKeys => { const appFeatureKeys = productTypes.reduce( (appFeatures, { product_line: line, product_tier: tier }) => { - if (tier === 'complete') { - // Adding all "essentials" PLIs when tier is "complete" - appFeatures.push(...PLI_APP_FEATURES[line].essentials); + if (tier === ProductTier.complete) { + appFeatures.push(...PLI_APP_FEATURES[line][ProductTier.essentials]); } appFeatures.push(...PLI_APP_FEATURES[line][tier]); return appFeatures; }, [] ); - return uniq(appFeatureKeys); + return appFeatureKeys; }; diff --git a/x-pack/plugins/security_solution_serverless/public/common/hooks/__mocks__/use_link_props.ts b/x-pack/plugins/security_solution_serverless/public/common/hooks/__mocks__/use_link_props.ts deleted file mode 100644 index 4941619cf3f99ff..000000000000000 --- a/x-pack/plugins/security_solution_serverless/public/common/hooks/__mocks__/use_link_props.ts +++ /dev/null @@ -1,16 +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 { GetLinkProps } from '../use_link_props'; - -export const getLinkProps = jest.fn(() => ({ - href: '/test-href', - onClick: jest.fn(), -})); - -export const useLinkProps: GetLinkProps = getLinkProps; -export const useGetLinkProps: () => GetLinkProps = jest.fn(() => getLinkProps); diff --git a/x-pack/plugins/security_solution_serverless/public/common/hooks/__mocks__/use_nav_links.ts b/x-pack/plugins/security_solution_serverless/public/common/hooks/__mocks__/use_nav_links.ts new file mode 100644 index 000000000000000..c108d41247a54c3 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/hooks/__mocks__/use_nav_links.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const useNavLinks = jest.fn(() => []); +export const useNavLink = jest.fn(() => undefined); diff --git a/x-pack/plugins/security_solution_serverless/public/common/hooks/use_link_props.test.tsx b/x-pack/plugins/security_solution_serverless/public/common/hooks/use_link_props.test.tsx deleted file mode 100644 index 5b4d215e331eadd..000000000000000 --- a/x-pack/plugins/security_solution_serverless/public/common/hooks/use_link_props.test.tsx +++ /dev/null @@ -1,157 +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 { MouseEvent } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; -import { APP_UI_ID, SecurityPageName } from '@kbn/security-solution-plugin/common'; -import { mockServices } from '../__mocks__/services.mock'; -import { useGetLinkProps, useLinkProps } from './use_link_props'; - -jest.mock('../services'); - -const href = '/app/security/test'; - -const { getUrlForApp, navigateToUrl } = mockServices.application; -const mockNavigateToUrl = navigateToUrl as jest.MockedFunction; -const mockGetUrlForApp = getUrlForApp as jest.MockedFunction; -mockGetUrlForApp.mockReturnValue(href); - -describe('useLinkProps', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should return link props', async () => { - const { result } = renderHook(useLinkProps); - - const linkProps = result.current; - - expect(linkProps).toEqual({ href, onClick: expect.any(Function) }); - expect(mockGetUrlForApp).toHaveBeenCalledTimes(1); - expect(mockGetUrlForApp).toHaveBeenCalledWith(APP_UI_ID, { - deepLinkId: undefined, - path: undefined, - }); - }); - - it('should call navigate when clicked normally', async () => { - const ev = { preventDefault: jest.fn() } as unknown as MouseEvent; - const { result } = renderHook(useLinkProps); - - const { onClick } = result.current; - onClick(ev); - - expect(mockNavigateToUrl).toHaveBeenCalledTimes(1); - expect(mockNavigateToUrl).toHaveBeenCalledWith(href); - }); - - it('should not call navigate when clicked with modifiers', async () => { - const ev = { preventDefault: jest.fn(), ctrlKey: true } as unknown as MouseEvent; - const { result } = renderHook(useLinkProps); - - const { onClick } = result.current; - onClick(ev); - - expect(mockNavigateToUrl).not.toHaveBeenCalled(); - }); - - it('should return link props passing deepLink', async () => { - const { result } = renderHook(useLinkProps, { - initialProps: { deepLinkId: SecurityPageName.alerts }, - }); - - const linkProps = result.current; - - expect(linkProps).toEqual({ href, onClick: expect.any(Function) }); - expect(mockGetUrlForApp).toHaveBeenCalledTimes(1); - expect(mockGetUrlForApp).toHaveBeenCalledWith(APP_UI_ID, { - deepLinkId: SecurityPageName.alerts, - path: undefined, - }); - }); - - it('should return link props passing deepLink and path', async () => { - const { result } = renderHook(useLinkProps, { - initialProps: { deepLinkId: SecurityPageName.alerts, path: '/test' }, - }); - - const linkProps = result.current; - - expect(linkProps).toEqual({ href, onClick: expect.any(Function) }); - expect(mockGetUrlForApp).toHaveBeenCalledTimes(1); - expect(mockGetUrlForApp).toHaveBeenCalledWith(APP_UI_ID, { - deepLinkId: SecurityPageName.alerts, - path: '/test', - }); - }); -}); - -describe('useGetLinkProps', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should return link props', async () => { - const { result } = renderHook(useGetLinkProps); - - const linkProps = result.current({}); - - expect(linkProps).toEqual({ href, onClick: expect.any(Function) }); - expect(mockGetUrlForApp).toHaveBeenCalledTimes(1); - expect(mockGetUrlForApp).toHaveBeenCalledWith(APP_UI_ID, { - deepLinkId: undefined, - path: undefined, - }); - }); - - it('should call navigate when clicked normally', async () => { - const ev = { preventDefault: jest.fn() } as unknown as MouseEvent; - const { result } = renderHook(useGetLinkProps); - - const { onClick } = result.current({}); - onClick(ev); - - expect(mockNavigateToUrl).toHaveBeenCalledTimes(1); - expect(mockNavigateToUrl).toHaveBeenCalledWith(href); - }); - - it('should not call navigate when clicked with modifiers', async () => { - const ev = { preventDefault: jest.fn(), ctrlKey: true } as unknown as MouseEvent; - const { result } = renderHook(useGetLinkProps); - - const { onClick } = result.current({}); - onClick(ev); - - expect(mockNavigateToUrl).not.toHaveBeenCalled(); - }); - - it('should return link props passing deepLink', async () => { - const { result } = renderHook(useGetLinkProps); - - const linkProps = result.current({ deepLinkId: SecurityPageName.alerts }); - - expect(linkProps).toEqual({ href, onClick: expect.any(Function) }); - expect(mockGetUrlForApp).toHaveBeenCalledTimes(1); - expect(mockGetUrlForApp).toHaveBeenCalledWith(APP_UI_ID, { - deepLinkId: SecurityPageName.alerts, - path: undefined, - }); - }); - - it('should return link props passing deepLink and path', async () => { - const { result } = renderHook(useGetLinkProps); - - const linkProps = result.current({ deepLinkId: SecurityPageName.alerts, path: '/test' }); - - expect(linkProps).toEqual({ href, onClick: expect.any(Function) }); - expect(mockGetUrlForApp).toHaveBeenCalledTimes(1); - expect(mockGetUrlForApp).toHaveBeenCalledWith(APP_UI_ID, { - deepLinkId: SecurityPageName.alerts, - path: '/test', - }); - }); -}); diff --git a/x-pack/plugins/security_solution_serverless/public/common/hooks/use_link_props.ts b/x-pack/plugins/security_solution_serverless/public/common/hooks/use_link_props.ts deleted file mode 100644 index 3a1989dbdc79a07..000000000000000 --- a/x-pack/plugins/security_solution_serverless/public/common/hooks/use_link_props.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { APP_UI_ID, type SecurityPageName } from '@kbn/security-solution-plugin/common'; -import { useMemo, useCallback, type MouseEventHandler, type MouseEvent } from 'react'; -import { useKibana, type Services } from '../services'; - -interface LinkProps { - onClick: MouseEventHandler; - href: string; -} - -interface GetLinkPropsParams { - deepLinkId?: SecurityPageName; - path?: string; - appId?: string; - onClick?: MouseEventHandler; -} - -export type GetLinkProps = (params: GetLinkPropsParams) => LinkProps; - -export const useLinkProps: GetLinkProps = (props) => { - const { application } = useKibana().services; - return useMemo(() => getLinkProps({ ...props, application }), [application, props]); -}; - -export const useGetLinkProps: () => GetLinkProps = () => { - const { application } = useKibana().services; - return useCallback( - (props) => getLinkProps({ ...props, application }), - [application] - ); -}; - -const getLinkProps = ({ - deepLinkId, - path, - onClick: onClickProps, - appId = APP_UI_ID, - application, -}: GetLinkPropsParams & { application: Services['application'] }): LinkProps => { - const { getUrlForApp, navigateToUrl } = application; - const url = getUrlForApp(appId, { deepLinkId, path }); - return { - href: url, - onClick: (ev) => { - if (isModifiedEvent(ev)) { - return; - } - - ev.preventDefault(); - navigateToUrl(url); - if (onClickProps) { - onClickProps(ev); - } - }, - }; -}; - -const isModifiedEvent = (event: MouseEvent) => - event.metaKey || event.altKey || event.ctrlKey || event.shiftKey; diff --git a/x-pack/plugins/security_solution_serverless/public/common/hooks/use_nav_links.ts b/x-pack/plugins/security_solution_serverless/public/common/hooks/use_nav_links.ts index 625e8362238228f..368cefdfaeae80b 100644 --- a/x-pack/plugins/security_solution_serverless/public/common/hooks/use_nav_links.ts +++ b/x-pack/plugins/security_solution_serverless/public/common/hooks/use_nav_links.ts @@ -7,6 +7,7 @@ import { useMemo } from 'react'; import useObservable from 'react-use/lib/useObservable'; +import type { ProjectPageName } from '../../navigation/links/types'; import { useKibana } from '../services'; export const useNavLinks = () => { @@ -14,3 +15,8 @@ export const useNavLinks = () => { const projectNavLinks$ = useMemo(() => getProjectNavLinks$(), [getProjectNavLinks$]); return useObservable(projectNavLinks$, []); }; + +export const useNavLink = (id: ProjectPageName) => { + const projectNavLinks = useNavLinks(); + return useMemo(() => projectNavLinks.find((navLink) => navLink.id === id), [projectNavLinks, id]); +}; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/auditbeat.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/auditbeat.tsx new file mode 100644 index 000000000000000..a8ee074b135dd30 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/auditbeat.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconAuditbeat: React.FC> = ({ ...props }) => ( + + + + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconAuditbeat; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/data_connector.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/data_connector.tsx new file mode 100644 index 000000000000000..26a4ca9ea24c951 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/data_connector.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconDataConnector: React.FC> = ({ ...props }) => ( + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconDataConnector; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/dev_tools.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/dev_tools.tsx new file mode 100644 index 000000000000000..49f2c129e4a79ee --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/dev_tools.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconDevTools: React.FC> = ({ ...props }) => ( + + + + + + + + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconDevTools; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/endpoint.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/endpoint.tsx new file mode 100644 index 000000000000000..20b8868aef4c01c --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/endpoint.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconEndpoint: React.FC> = ({ ...props }) => ( + + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconEndpoint; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/fleet.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/fleet.tsx new file mode 100644 index 000000000000000..5454dca71b1e8f5 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/fleet.tsx @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { SVGProps } from 'react'; +import React from 'react'; +export const IconFleet: React.FC> = ({ ...props }) => ( + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconFleet; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/index_management.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/index_management.tsx new file mode 100644 index 000000000000000..8684c5bd0527997 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/index_management.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconIndexManagement: React.FC> = ({ ...props }) => ( + + + + + + + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconIndexManagement; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/lens.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/lens.tsx new file mode 100644 index 000000000000000..322e99ace649c87 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/lens.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconLens: React.FC> = ({ ...props }) => ( + + + + + + + + + + + + + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconLens; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/searchable_snapshots.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/searchable_snapshots.tsx new file mode 100644 index 000000000000000..9b199309fdee902 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/searchable_snapshots.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconSearchableSnapshots: React.FC> = ({ ...props }) => ( + + + + + + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconSearchableSnapshots; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/siem.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/siem.tsx new file mode 100644 index 000000000000000..00b775af8fa36aa --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/siem.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconSiem: React.FC> = ({ ...props }) => ( + + + + + + + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconSiem; diff --git a/x-pack/plugins/security_solution_serverless/public/common/icons/spaces.tsx b/x-pack/plugins/security_solution_serverless/public/common/icons/spaces.tsx new file mode 100644 index 000000000000000..1a5e6300b1b9f4e --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/icons/spaces.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. + */ +import type { SVGProps } from 'react'; +import React from 'react'; +export const IconSpaces: React.FC> = ({ ...props }) => ( + + + + + + + + + + + + +); + +// eslint-disable-next-line import/no-default-export +export default IconSpaces; diff --git a/x-pack/plugins/security_solution_serverless/public/common/lazy_icons.tsx b/x-pack/plugins/security_solution_serverless/public/common/lazy_icons.tsx new file mode 100644 index 000000000000000..18c5afc9397a29d --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/lazy_icons.tsx @@ -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 React, { Suspense } from 'react'; +import { EuiLoadingSpinner } from '@elastic/eui'; + +const withSuspenseIcon = (Component: React.ComponentType): React.FC => + function WithSuspenseIcon(props) { + return ( + }> + + + ); + }; + +export const IconLensLazy = withSuspenseIcon(React.lazy(() => import('./icons/lens'))); +export const IconEndpointLazy = withSuspenseIcon(React.lazy(() => import('./icons/endpoint'))); +export const IconDataConnectorLazy = withSuspenseIcon( + React.lazy(() => import('./icons/data_connector')) +); +export const IconIndexManagementLazy = withSuspenseIcon( + React.lazy(() => import('./icons/index_management')) +); +export const IconSpacesLazy = withSuspenseIcon(React.lazy(() => import('./icons/spaces'))); +export const IconDevToolsLazy = withSuspenseIcon(React.lazy(() => import('./icons/dev_tools'))); +export const IconFleetLazy = withSuspenseIcon(React.lazy(() => import('./icons/fleet'))); +export const IconAuditbeatLazy = withSuspenseIcon(React.lazy(() => import('./icons/auditbeat'))); +export const IconSiemLazy = withSuspenseIcon(React.lazy(() => import('./icons/siem'))); diff --git a/x-pack/plugins/security_solution_serverless/public/common/__mocks__/services.tsx b/x-pack/plugins/security_solution_serverless/public/common/services/__mocks__/index.tsx similarity index 50% rename from x-pack/plugins/security_solution_serverless/public/common/__mocks__/services.tsx rename to x-pack/plugins/security_solution_serverless/public/common/services/__mocks__/index.tsx index 5c6d2f1117c64fb..7d7dd9d75e8c34f 100644 --- a/x-pack/plugins/security_solution_serverless/public/common/__mocks__/services.tsx +++ b/x-pack/plugins/security_solution_serverless/public/common/services/__mocks__/index.tsx @@ -9,11 +9,24 @@ import React from 'react'; import { I18nProvider } from '@kbn/i18n-react'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { mockServices } from './services.mock'; +import { NavigationProvider } from '@kbn/security-solution-navigation'; -export const KibanaServicesProvider: React.FC = ({ children }) => ( +export const ServicesProvider: React.FC = ({ children }) => ( - {children} + + {children} + ); +export const withServicesProvider = (Component: React.ComponentType) => { + return function WithServicesProvider(props: T) { + return ( + + + + ); + }; +}; + export const useKibana = jest.fn(() => ({ services: mockServices })); diff --git a/x-pack/plugins/security_solution_serverless/public/common/__mocks__/services.mock.tsx b/x-pack/plugins/security_solution_serverless/public/common/services/__mocks__/services.mock.tsx similarity index 68% rename from x-pack/plugins/security_solution_serverless/public/common/__mocks__/services.mock.tsx rename to x-pack/plugins/security_solution_serverless/public/common/services/__mocks__/services.mock.tsx index e4b1c777191efb3..29ed99cb9fc744f 100644 --- a/x-pack/plugins/security_solution_serverless/public/common/__mocks__/services.mock.tsx +++ b/x-pack/plugins/security_solution_serverless/public/common/services/__mocks__/services.mock.tsx @@ -4,17 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; -import { I18nProvider } from '@kbn/i18n-react'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { coreMock } from '@kbn/core/public/mocks'; import { serverlessMock } from '@kbn/serverless/public/mocks'; import { securityMock } from '@kbn/security-plugin/public/mocks'; import { securitySolutionMock } from '@kbn/security-solution-plugin/public/mocks'; import { BehaviorSubject } from 'rxjs'; import { managementPluginMock } from '@kbn/management-plugin/public/mocks'; -import type { ProjectNavigationLink } from '../../navigation/links'; -import type { Services } from '../services'; +import type { ProjectNavigationLink } from '../../../navigation/links/types'; +import type { Services } from '..'; export const mockProjectNavLinks = jest.fn((): ProjectNavigationLink[] => []); @@ -26,11 +23,3 @@ export const mockServices: Services = { getProjectNavLinks$: jest.fn(() => new BehaviorSubject(mockProjectNavLinks())), management: managementPluginMock.createStartContract(), }; - -export const ServicesWrapper = React.memo(function ServicesWrapper({ children }) { - return ( - - {children} - - ); -}); diff --git a/x-pack/plugins/security_solution_serverless/public/common/services.tsx b/x-pack/plugins/security_solution_serverless/public/common/services/create_services.ts similarity index 50% rename from x-pack/plugins/security_solution_serverless/public/common/services.tsx rename to x-pack/plugins/security_solution_serverless/public/common/services/create_services.ts index 799b2e5913c0a33..e4213de19e1fe4c 100644 --- a/x-pack/plugins/security_solution_serverless/public/common/services.tsx +++ b/x-pack/plugins/security_solution_serverless/public/common/services/create_services.ts @@ -6,33 +6,15 @@ */ import type { CoreStart } from '@kbn/core/public'; -import React from 'react'; -import { - KibanaContextProvider, - useKibana as useKibanaReact, -} from '@kbn/kibana-react-plugin/public'; - -import type { SecuritySolutionServerlessPluginStartDeps } from '../types'; -import { getProjectNavLinks$, type ProjectNavLinks } from '../navigation/links'; - -interface InternalServices { - getProjectNavLinks$: () => ProjectNavLinks; -} -export type Services = CoreStart & SecuritySolutionServerlessPluginStartDeps & InternalServices; - -export const KibanaServicesProvider: React.FC<{ - services: Services; -}> = ({ services, children }) => { - return {children}; -}; - -export const useKibana = () => useKibanaReact(); +import { getProjectNavLinks$ } from '../../navigation/links/nav_links'; +import type { SecuritySolutionServerlessPluginStartDeps } from '../../types'; +import type { Services } from './types'; export const createServices = ( core: CoreStart, pluginsStart: SecuritySolutionServerlessPluginStartDeps ): Services => { const { securitySolution } = pluginsStart; - const projectNavLinks$ = getProjectNavLinks$(securitySolution.getNavLinks$()); + const projectNavLinks$ = getProjectNavLinks$(securitySolution.getNavLinks$(), core); return { ...core, ...pluginsStart, getProjectNavLinks$: () => projectNavLinks$ }; }; diff --git a/x-pack/plugins/security_solution_serverless/public/common/services/index.tsx b/x-pack/plugins/security_solution_serverless/public/common/services/index.tsx new file mode 100644 index 000000000000000..f9dc21956d727d4 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/services/index.tsx @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { ServicesProvider, withServicesProvider, useKibana } from './services'; +export type { Services } from './types'; diff --git a/x-pack/plugins/security_solution_serverless/public/common/services/services.tsx b/x-pack/plugins/security_solution_serverless/public/common/services/services.tsx new file mode 100644 index 000000000000000..41097b1ea470f03 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/services/services.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { + KibanaContextProvider, + useKibana as useKibanaReact, +} from '@kbn/kibana-react-plugin/public'; +import { NavigationProvider } from '@kbn/security-solution-navigation'; +import type { Services } from './types'; + +export const ServicesProvider: React.FC<{ + services: Services; +}> = ({ services, children }) => { + return ( + + {children} + + ); +}; + +export const withServicesProvider = ( + Component: React.ComponentType, + services: Services +) => { + return function WithServicesProvider(props: T) { + return ( + + + + ); + }; +}; + +export const useKibana = () => useKibanaReact(); diff --git a/x-pack/plugins/security_solution_serverless/public/common/services/types.ts b/x-pack/plugins/security_solution_serverless/public/common/services/types.ts new file mode 100644 index 000000000000000..c655f7db6898d97 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/common/services/types.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 type { CoreStart } from '@kbn/core/public'; +import type { ProjectNavLinks } from '../../navigation/links/types'; +import type { SecuritySolutionServerlessPluginStartDeps } from '../../types'; + +export interface InternalServices { + getProjectNavLinks$: () => ProjectNavLinks; +} +export type Services = CoreStart & SecuritySolutionServerlessPluginStartDeps & InternalServices; diff --git a/x-pack/plugins/security_solution_serverless/public/get_started/index.tsx b/x-pack/plugins/security_solution_serverless/public/get_started/index.tsx index c457d47a3da3087..3be88d10800744f 100644 --- a/x-pack/plugins/security_solution_serverless/public/get_started/index.tsx +++ b/x-pack/plugins/security_solution_serverless/public/get_started/index.tsx @@ -7,7 +7,7 @@ import React from 'react'; -import { KibanaServicesProvider, type Services } from '../common/services'; +import { ServicesProvider, type Services } from '../common/services'; import { GetStarted } from './lazy'; import type { SecurityProductTypes } from '../../common/config'; @@ -17,8 +17,8 @@ export const getSecurityGetStartedComponent = ( ): React.ComponentType => function GetStartedComponent() { return ( - + - + ); }; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/index.ts b/x-pack/plugins/security_solution_serverless/public/navigation/index.ts index 226c20997ef5e8a..374f2b9af57f805 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/index.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/index.ts @@ -8,15 +8,13 @@ import { APP_PATH, MANAGE_PATH } from '@kbn/security-solution-plugin/common'; import type { Services } from '../common/services'; import { subscribeBreadcrumbs } from './breadcrumbs'; +import { setAppLinks } from './links/app_links'; import { subscribeNavigationTree } from './navigation_tree'; import { getSecuritySideNavComponent } from './side_navigation'; const SECURITY_MANAGE_PATH = `${APP_PATH}${MANAGE_PATH}`; -/** - * Configures the serverless project navigation - */ -export const setServerlessNavigation = (services: Services) => { +export const configureNavigation = (services: Services) => { const { serverless, securitySolution, management } = services; securitySolution.setIsSidebarEnabled(false); management.setLandingPageRedirect(SECURITY_MANAGE_PATH); @@ -24,6 +22,7 @@ export const setServerlessNavigation = (services: Services) => { serverless.setProjectHome(APP_PATH); serverless.setSideNavComponent(getSecuritySideNavComponent(services)); + setAppLinks(services); subscribeNavigationTree(services); subscribeBreadcrumbs(services); }; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/app_links.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/app_links.ts new file mode 100644 index 000000000000000..536d07066fa7c16 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/app_links.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 type { Services } from '../../common/services'; +import { mlAppLink } from './sections/ml_links'; + +export const setAppLinks = (services: Services) => { + services.securitySolution.setExtraAppLinks([ + mlAppLink, // ML landing page app link + ]); +}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/constants.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/constants.ts new file mode 100644 index 000000000000000..a4edec4bac6f66b --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/constants.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SecurityPageName } from '@kbn/security-solution-navigation'; + +export const SecurityPagePath = { + [SecurityPageName.mlLanding]: '/ml', +} as const; + +export enum ExternalPageName { + // Machine Learning + // Ref: packages/default-nav/ml/default_navigation.ts + mlOverview = 'ml:overview', + mlNotifications = 'ml:notifications', + mlAnomalyDetection = 'ml:anomalyDetection', + mlAnomalyExplorer = 'ml:anomalyExplorer', + mlSingleMetricViewer = 'ml:singleMetricViewer', + mlSettings = 'ml:settings', + mlDataFrameAnalytics = 'ml:dataFrameAnalytics', + mlResultExplorer = 'ml:resultExplorer', + mlAnalyticsMap = 'ml:analyticsMap', + mlNodesOverview = 'ml:nodesOverview', + mlNodes = 'ml:nodes', + mlFileUpload = 'ml:fileUpload', + mlIndexDataVisualizer = 'ml:indexDataVisualizer', + mlExplainLogRateSpikes = 'ml:explainLogRateSpikes', + mlLogPatternAnalysis = 'ml:logPatternAnalysis', + mlChangePointDetections = 'ml:changePointDetections', + // Dev Tools + // Ref: packages/default-nav/devtools/default_navigation.ts + devToolsRoot = 'dev_tools:', +} diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/nav.links.test.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/nav.links.test.ts new file mode 100644 index 000000000000000..0cb6cbf61234210 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/nav.links.test.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { ChromeNavLink } from '@kbn/core/public'; +import { APP_UI_ID } from '@kbn/security-solution-plugin/common'; +import type { NavigationLink } from '@kbn/security-solution-navigation'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; +import { getProjectNavLinks$ } from './nav_links'; +import { BehaviorSubject, firstValueFrom, take } from 'rxjs'; +import { mockServices } from '../../common/services/__mocks__/services.mock'; +import { mlNavCategories, mlNavLinks } from './sections/ml_links'; +import { ExternalPageName } from './constants'; +import type { ProjectNavigationLink } from './types'; + +const mockChromeNavLinks = jest.fn((): ChromeNavLink[] => []); +const mockChromeGetNavLinks = jest.fn(() => new BehaviorSubject(mockChromeNavLinks())); +const mockChromeNavLinksHas = jest.fn((id: string): boolean => + mockChromeNavLinks().some((link) => link.id === id) +); +const testServices = { + ...mockServices, + chrome: { + ...mockServices.chrome, + navLinks: { + ...mockServices.chrome.navLinks, + has: mockChromeNavLinksHas, + getNavLinks$: mockChromeGetNavLinks, + }, + }, +}; + +const link1Id = 'link-1' as SecurityPageName; +const link2Id = 'link-2' as SecurityPageName; + +const link1: NavigationLink = { id: link1Id, title: 'link 1' }; +const link2: NavigationLink = { id: link2Id, title: 'link 2' }; +const linkMlLanding: NavigationLink = { + id: SecurityPageName.mlLanding, + title: 'ML Landing', + links: [], +}; +const projectLinkDevTools: ProjectNavigationLink = { + id: ExternalPageName.devToolsRoot, + title: 'Dev Tools', +}; + +const chromeNavLink1: ChromeNavLink = { + id: `${APP_UI_ID}:${link1.id}`, + title: link1.title, + href: '/link1', + url: '/link1', + baseUrl: '', +}; +const devToolsNavLink: ChromeNavLink = { + id: 'dev_tools', + title: 'Dev Tools', + href: '/dev_tools', + url: '/dev_tools', + baseUrl: '', +}; + +describe('getProjectNavLinks', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockChromeNavLinks.mockReturnValue([chromeNavLink1]); + mockChromeNavLinksHas.mockImplementation((id: string): boolean => + mockChromeNavLinks().some((link) => link.id === id) + ); + }); + + it('should return security nav links with all external links filtered', async () => { + mockChromeNavLinksHas.mockReturnValue(false); // no external links exist + const testSecurityNavLinks$ = new BehaviorSubject([link1, link2]); + + const projectNavLinks$ = getProjectNavLinks$(testSecurityNavLinks$, testServices); + const value = await firstValueFrom(projectNavLinks$.pipe(take(1))); + expect(value).toEqual([link1, link2]); + }); + + it('should add devTools nav link if chrome nav link exists', async () => { + mockChromeNavLinks.mockReturnValue([devToolsNavLink]); + const testSecurityNavLinks$ = new BehaviorSubject([link1]); + + const projectNavLinks$ = getProjectNavLinks$(testSecurityNavLinks$, testServices); + + const value = await firstValueFrom(projectNavLinks$.pipe(take(1))); + expect(value).toEqual([link1, projectLinkDevTools]); + }); + + it('should add machineLearning landing nav link filtering all external links', async () => { + mockChromeNavLinks.mockReturnValue([chromeNavLink1]); + const testSecurityNavLinks$ = new BehaviorSubject([link1, link2, linkMlLanding]); + + const projectNavLinks$ = getProjectNavLinks$(testSecurityNavLinks$, testServices); + + const value = await firstValueFrom(projectNavLinks$.pipe(take(1))); + expect(value).toEqual([ + link1, + link2, + expect.objectContaining({ id: SecurityPageName.mlLanding, links: [] }), + ]); + }); + + it('should add machineLearning and devTools nav links with all external links present', async () => { + mockChromeNavLinksHas.mockReturnValue(true); // all external links exist + const testSecurityNavLinks$ = new BehaviorSubject([link1, link2, linkMlLanding]); + + const projectNavLinks$ = getProjectNavLinks$(testSecurityNavLinks$, testServices); + + const value = await firstValueFrom(projectNavLinks$.pipe(take(1))); + expect(value).toEqual([ + link1, + link2, + { ...linkMlLanding, categories: mlNavCategories, links: mlNavLinks }, + projectLinkDevTools, + ]); + }); +}); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/nav_links.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/nav_links.ts index 289d0a0c5570807..edda1d38f88044f 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/links/nav_links.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/nav_links.ts @@ -5,14 +5,79 @@ * 2.0. */ -import { map, type Observable } from 'rxjs'; -import type { NavigationLink } from '@kbn/security-solution-plugin/public'; -import type { ProjectNavLinks, ProjectNavigationLink } from './types'; +import { map, combineLatest, skipWhile, debounceTime, type Observable } from 'rxjs'; +import type { ChromeNavLinks, CoreStart } from '@kbn/core/public'; +import { SecurityPageName, type NavigationLink } from '@kbn/security-solution-navigation'; +import { isExternalId } from '@kbn/security-solution-navigation/links'; +import { mlNavCategories, mlNavLinks } from './sections/ml_links'; +import { devToolsNavLink } from './sections/dev_tools_links'; +import type { ProjectNavigationLink } from './types'; +import { getNavLinkIdFromProjectPageName } from './util'; -export const getProjectNavLinks$ = (navLinks$: Observable): ProjectNavLinks => { - return navLinks$.pipe(map(processNavLinks)); +export const getProjectNavLinks$ = ( + securityNavLinks$: Observable>>, + core: CoreStart +): Observable => { + const { chrome } = core; + return combineLatest([securityNavLinks$, chrome.navLinks.getNavLinks$()]).pipe( + debounceTime(100), // avoid multiple calls in a short period of time + skipWhile( + ([securityNavLinks, chromeNavLinks]) => + securityNavLinks.length === 0 || chromeNavLinks.length === 0 // skip if not initialized + ), + map(([securityNavLinks]) => processNavLinks(securityNavLinks, chrome.navLinks)) + ); }; -// TODO: This is a placeholder function that will be used to process the nav links, -// It will mix internal Security nav links with the external links to other plugins, in the correct order. -const processNavLinks = (navLinks: NavigationLink[]): ProjectNavigationLink[] => navLinks; +/** + * Takes the security nav links and the chrome nav links and generates the project nav links + * containing Security internal nav links and the external nav links (ML, Dev Tools, Project Settings, etc.) + */ +const processNavLinks = ( + securityNavLinks: Array>, + chromeNavLinks: ChromeNavLinks +): ProjectNavigationLink[] => { + const projectNavLinks: ProjectNavigationLink[] = [...securityNavLinks]; + + // ML. injecting external sub-links and categories definition to the landing + const mlLinkIndex = projectNavLinks.findIndex(({ id }) => id === SecurityPageName.mlLanding); + if (mlLinkIndex !== -1) { + projectNavLinks[mlLinkIndex] = { + ...projectNavLinks[mlLinkIndex], + categories: mlNavCategories, + links: mlNavLinks, + }; + } + + // Dev Tools. just pushing it + projectNavLinks.push(devToolsNavLink); + + // TODO: Project Settings. Override "Settings" link + + return filterDisabled(projectNavLinks, chromeNavLinks); +}; + +/** + * Filters out the disabled external nav links from the project nav links. + * Internal Security links are already filtered by the security_solution plugin appLinks. + */ +const filterDisabled = ( + projectNavLinks: ProjectNavigationLink[], + chromeNavLinks: ChromeNavLinks +): ProjectNavigationLink[] => { + return projectNavLinks.reduce((filteredNavLinks, navLink) => { + const { id, links } = navLink; + if (isExternalId(id)) { + const navLinkId = getNavLinkIdFromProjectPageName(id); + if (!chromeNavLinks.has(navLinkId)) { + return filteredNavLinks; + } + } + if (links) { + filteredNavLinks.push({ ...navLink, links: filterDisabled(links, chromeNavLinks) }); + } else { + filteredNavLinks.push(navLink); + } + return filteredNavLinks; + }, []); +}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/dev_tools_links.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/dev_tools_links.ts new file mode 100644 index 000000000000000..7bf50a3e2452f63 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/dev_tools_links.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 { ExternalPageName } from '../constants'; +import type { ProjectNavigationLink } from '../types'; +import { DEV_TOOLS_TITLE } from './translations'; + +export const devToolsNavLink: ProjectNavigationLink = { + id: ExternalPageName.devToolsRoot, + title: DEV_TOOLS_TITLE, +}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/ml_links.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/ml_links.ts new file mode 100644 index 000000000000000..d80dd32552d81e2 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/ml_links.ts @@ -0,0 +1,181 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SecurityPageName, LinkCategoryType } from '@kbn/security-solution-navigation'; +import { SERVER_APP_ID } from '@kbn/security-solution-plugin/common'; +import type { LinkItem } from '@kbn/security-solution-plugin/public'; +import { ExternalPageName, SecurityPagePath } from '../constants'; +import type { ProjectLinkCategory, ProjectNavigationLink } from '../types'; +import * as i18n from './translations'; +import { + IconLensLazy, + IconEndpointLazy, + IconSpacesLazy, + IconIndexManagementLazy, + IconDataConnectorLazy, + IconDevToolsLazy, + IconFleetLazy, + IconAuditbeatLazy, + IconSiemLazy, +} from '../../../common/lazy_icons'; + +// appLinks configures the Security Solution pages links +export const mlAppLink: LinkItem = { + id: SecurityPageName.mlLanding, + title: i18n.ML_TITLE, + path: SecurityPagePath[SecurityPageName.mlLanding], + capabilities: [`${SERVER_APP_ID}.show`], + globalSearchKeywords: [i18n.ML_KEYWORD], + hideTimeline: true, + skipUrlState: true, + links: [], // no security internal links +}; + +export const mlNavCategories: ProjectLinkCategory[] = [ + { + type: LinkCategoryType.separator, + linkIds: [ExternalPageName.mlOverview, ExternalPageName.mlNotifications], + }, + { + type: LinkCategoryType.title, + label: i18n.ANOMALY_DETECTION_CATEGORY, + linkIds: [ + ExternalPageName.mlAnomalyDetection, + ExternalPageName.mlAnomalyExplorer, + ExternalPageName.mlSingleMetricViewer, + ExternalPageName.mlSettings, + ], + }, + { + type: LinkCategoryType.title, + label: i18n.DATA_FRAME_ANALYTICS_CATEGORY, + linkIds: [ + ExternalPageName.mlDataFrameAnalytics, + ExternalPageName.mlResultExplorer, + ExternalPageName.mlAnalyticsMap, + ], + }, + { + type: LinkCategoryType.title, + label: i18n.MODEL_MANAGEMENT_CATEGORY, + linkIds: [ExternalPageName.mlNodesOverview, ExternalPageName.mlNodes], + }, + { + type: LinkCategoryType.title, + label: i18n.DATA_VISUALIZER_CATEGORY, + linkIds: [ExternalPageName.mlFileUpload, ExternalPageName.mlIndexDataVisualizer], + }, + { + type: LinkCategoryType.title, + label: i18n.AIOPS_LABS_CATEGORY, + linkIds: [ + ExternalPageName.mlExplainLogRateSpikes, + ExternalPageName.mlLogPatternAnalysis, + ExternalPageName.mlChangePointDetections, + ], + }, +]; + +// navLinks define the navigation links for the Security Solution pages and External pages as well +export const mlNavLinks: ProjectNavigationLink[] = [ + { + id: ExternalPageName.mlOverview, + title: i18n.OVERVIEW_TITLE, + landingIcon: IconLensLazy, + description: i18n.OVERVIEW_DESC, + }, + { + id: ExternalPageName.mlNotifications, + title: i18n.NOTIFICATIONS_TITLE, + landingIcon: IconEndpointLazy, + description: i18n.NOTIFICATIONS_DESC, + }, + { + id: ExternalPageName.mlAnomalyDetection, + title: i18n.ANOMALY_DETECTION_TITLE, + landingIcon: IconSpacesLazy, + description: i18n.ANOMALY_DETECTION_DESC, + }, + { + id: ExternalPageName.mlAnomalyExplorer, + title: i18n.ANOMALY_EXPLORER_TITLE, + landingIcon: IconIndexManagementLazy, + description: i18n.ANOMALY_EXPLORER_DESC, + }, + { + id: ExternalPageName.mlSingleMetricViewer, + title: i18n.SINGLE_METRIC_VIEWER_TITLE, + landingIcon: IconDataConnectorLazy, + description: i18n.SINGLE_METRIC_VIEWER_DESC, + }, + { + id: ExternalPageName.mlSettings, + title: i18n.SETTINGS_TITLE, + landingIcon: IconDevToolsLazy, + description: i18n.SETTINGS_DESC, + }, + { + id: ExternalPageName.mlDataFrameAnalytics, + title: i18n.DATA_FRAME_ANALYTICS_TITLE, + landingIcon: IconIndexManagementLazy, + description: i18n.DATA_FRAME_ANALYTICS_DESC, + }, + { + id: ExternalPageName.mlResultExplorer, + title: i18n.RESULT_EXPLORER_TITLE, + landingIcon: IconFleetLazy, + description: i18n.RESULT_EXPLORER_DESC, + }, + { + id: ExternalPageName.mlAnalyticsMap, + title: i18n.ANALYTICS_MAP_TITLE, + landingIcon: IconAuditbeatLazy, + description: i18n.ANALYTICS_MAP_DESC, + }, + { + id: ExternalPageName.mlNodesOverview, + title: i18n.NODES_OVERVIEW_TITLE, + landingIcon: IconSiemLazy, + description: i18n.NODES_OVERVIEW_DESC, + }, + { + id: ExternalPageName.mlNodes, + title: i18n.NODES_TITLE, + landingIcon: IconEndpointLazy, + description: i18n.NODES_DESC, + }, + { + id: ExternalPageName.mlFileUpload, + title: i18n.FILE_UPLOAD_TITLE, + landingIcon: IconEndpointLazy, + description: i18n.FILE_UPLOAD_DESC, + }, + { + id: ExternalPageName.mlIndexDataVisualizer, + title: i18n.INDEX_DATA_VISUALIZER_TITLE, + landingIcon: IconEndpointLazy, + description: i18n.INDEX_DATA_VISUALIZER_DESC, + }, + { + id: ExternalPageName.mlExplainLogRateSpikes, + title: i18n.EXPLAIN_LOG_RATE_SPIKES_TITLE, + landingIcon: IconEndpointLazy, + description: i18n.EXPLAIN_LOG_RATE_SPIKES_DESC, + }, + { + id: ExternalPageName.mlLogPatternAnalysis, + title: i18n.LOG_PATTERN_ANALYSIS_TITLE, + landingIcon: IconEndpointLazy, + description: i18n.LOG_PATTERN_ANALYSIS_DESC, + }, + { + id: ExternalPageName.mlChangePointDetections, + title: i18n.CHANGE_POINT_DETECTIONS_TITLE, + landingIcon: IconEndpointLazy, + description: i18n.CHANGE_POINT_DETECTIONS_DESC, + }, +]; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/translations.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/translations.ts new file mode 100644 index 000000000000000..a1e75705516d7e7 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/sections/translations.ts @@ -0,0 +1,246 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 ML_TITLE = i18n.translate('xpack.securitySolutionServerless.appLinks.ml.title', { + defaultMessage: 'Machine Learning', +}); +export const ML_KEYWORD = i18n.translate('xpack.securitySolutionServerless.appLinks.ml.keyword', { + defaultMessage: 'Machine Learning', +}); + +export const ANOMALY_DETECTION_CATEGORY = i18n.translate( + 'xpack.securitySolutionServerless.navCategories.ml.anomalyDetection.title', + { + defaultMessage: 'Anomaly Detection', + } +); +export const DATA_FRAME_ANALYTICS_CATEGORY = i18n.translate( + 'xpack.securitySolutionServerless.navCategories.ml.dataFrameAnalyticstitle', + { + defaultMessage: 'Data Frame Analytics', + } +); +export const MODEL_MANAGEMENT_CATEGORY = i18n.translate( + 'xpack.securitySolutionServerless.navCategories.ml.modelManagement.title', + { + defaultMessage: 'Model Management', + } +); +export const DATA_VISUALIZER_CATEGORY = i18n.translate( + 'xpack.securitySolutionServerless.navCategories.ml.dataVisualizer.title', + { + defaultMessage: 'Data Visualizer', + } +); +export const AIOPS_LABS_CATEGORY = i18n.translate( + 'xpack.securitySolutionServerless.navCategories.ml.aiopsLabs.title', + { + defaultMessage: 'Aiops Labs', + } +); + +export const OVERVIEW_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.overview.title', + { + defaultMessage: 'Overview', + } +); +export const OVERVIEW_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.overview.desc', + { + defaultMessage: 'Overview Page', + } +); +export const NOTIFICATIONS_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.notifications.title', + { + defaultMessage: 'Notifications', + } +); +export const NOTIFICATIONS_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.notifications.desc', + { + defaultMessage: 'Notifications Page', + } +); +export const ANOMALY_DETECTION_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.anomalyDetection.title', + { + defaultMessage: 'Jobs', + } +); +export const ANOMALY_DETECTION_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.anomalyDetection.desc', + { + defaultMessage: 'Jobs Page', + } +); +export const ANOMALY_EXPLORER_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.anomalyExplorer.title', + { + defaultMessage: 'Anomaly Explorer', + } +); +export const ANOMALY_EXPLORER_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.anomalyExplorer.desc', + { + defaultMessage: 'Anomaly Explorer Page', + } +); +export const SINGLE_METRIC_VIEWER_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.singleMetricViewer.title', + { + defaultMessage: 'Single Metric Viewer', + } +); +export const SINGLE_METRIC_VIEWER_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.singleMetricViewer.desc', + { + defaultMessage: 'Single Metric Viewer Page', + } +); +export const SETTINGS_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.settings.title', + { + defaultMessage: 'Settings', + } +); +export const SETTINGS_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.settings.desc', + { + defaultMessage: 'Settings Page', + } +); +export const DATA_FRAME_ANALYTICS_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.dataFrameAnalytics.title', + { + defaultMessage: 'Jobs', + } +); +export const DATA_FRAME_ANALYTICS_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.dataFrameAnalytics.desc', + { + defaultMessage: 'Jobs Page', + } +); +export const RESULT_EXPLORER_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.resultExplorer.title', + { + defaultMessage: 'Result Explorer', + } +); +export const RESULT_EXPLORER_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.resultExplorer.desc', + { + defaultMessage: 'Result Explorer Page', + } +); +export const ANALYTICS_MAP_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.analyticsMap.title', + { + defaultMessage: 'Analytics Map', + } +); +export const ANALYTICS_MAP_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.analyticsMap.desc', + { + defaultMessage: 'Analytics Map Page', + } +); +export const NODES_OVERVIEW_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.nodesOverview.title', + { + defaultMessage: 'Nodes Overview', + } +); +export const NODES_OVERVIEW_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.nodesOverview.desc', + { + defaultMessage: 'Nodes Overview Page', + } +); +export const NODES_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.nodes.title', + { + defaultMessage: 'Nodes', + } +); +export const NODES_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.nodes.desc', + { + defaultMessage: 'Nodes Page', + } +); +export const FILE_UPLOAD_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.fileUpload.title', + { + defaultMessage: 'File', + } +); +export const FILE_UPLOAD_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.fileUpload.desc', + { + defaultMessage: 'File Page', + } +); +export const INDEX_DATA_VISUALIZER_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.indexDataVisualizer.title', + { + defaultMessage: 'Data view', + } +); +export const INDEX_DATA_VISUALIZER_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.indexDataVisualizer.desc', + { + defaultMessage: 'Data view Page', + } +); +export const EXPLAIN_LOG_RATE_SPIKES_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.explainLogRateSpikes.title', + { + defaultMessage: 'Explain Log Rate Spikes', + } +); +export const EXPLAIN_LOG_RATE_SPIKES_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.explainLogRateSpikes.desc', + { + defaultMessage: 'Explain Log Rate Spikes Page', + } +); +export const LOG_PATTERN_ANALYSIS_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.logPatternAnalysis.title', + { + defaultMessage: 'Log Pattern Analysis', + } +); +export const LOG_PATTERN_ANALYSIS_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.logPatternAnalysis.desc', + { + defaultMessage: 'Log Pattern Analysis Page', + } +); +export const CHANGE_POINT_DETECTIONS_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.changePointDetections.title', + { + defaultMessage: 'Change Point Detections', + } +); +export const CHANGE_POINT_DETECTIONS_DESC = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.ml.changePointDetections.desc', + { + defaultMessage: 'Change Point Detections Page', + } +); + +export const DEV_TOOLS_TITLE = i18n.translate( + 'xpack.securitySolutionServerless.navLinks.devTools.title', + { + defaultMessage: 'Dev Tools', + } +); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/types.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/types.ts index 47930f64dd6d870..929724a0ddfadde 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/links/types.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/types.ts @@ -6,11 +6,15 @@ */ import type { Observable } from 'rxjs'; -import type { NavigationLink } from '@kbn/security-solution-plugin/public'; +import type { + SecurityPageName, + NavigationLink, + LinkCategory, +} from '@kbn/security-solution-navigation'; +import type { ExternalPageName } from './constants'; -export interface ProjectNavigationLink extends NavigationLink { - // The appId for external links - appId?: string; -} +export type ProjectPageName = SecurityPageName | ExternalPageName | 'root'; +export type ProjectNavigationLink = NavigationLink; +export type ProjectLinkCategory = LinkCategory; export type ProjectNavLinks = Observable; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/util.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/util.ts new file mode 100644 index 000000000000000..5501c475e68b556 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/util.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 { APP_UI_ID } from '@kbn/security-solution-plugin/common'; +import type { ProjectPageName } from './types'; + +export const getNavLinkIdFromProjectPageName = (projectNavLinkId: ProjectPageName): string => { + const fullId = projectNavLinkId.includes(':') + ? projectNavLinkId + : `${APP_UI_ID}:${projectNavLinkId}`; // add the Security appId if not defined + return fullId.replace(/:$/, ''); // clean trailing separator to app root links to contain the appId alone +}; + +export const getProjectPageNameFromNavLinkId = (navLinkId: string): ProjectPageName => { + const cleanId = navLinkId.includes(':') ? navLinkId : `${navLinkId}:`; // add trailing separator to app root links that contain the appId alone + const fullId = cleanId.replace(`${APP_UI_ID}:`, ''); // remove Security appId if present + return fullId as ProjectPageName; +}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree.test.ts b/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree.test.ts index b1e619a30fc1359..b7da21cb5e1cd74 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree.test.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree.test.ts @@ -5,39 +5,23 @@ * 2.0. */ import type { ChromeNavLink } from '@kbn/core/public'; -import { APP_UI_ID, SecurityPageName } from '@kbn/security-solution-plugin/common'; +import { APP_UI_ID } from '@kbn/security-solution-plugin/common'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; import { subscribeNavigationTree } from './navigation_tree'; -import { BehaviorSubject } from 'rxjs'; -import { mockServices, mockProjectNavLinks } from '../common/__mocks__/services.mock'; -import type { ProjectNavigationLink } from './links'; +import { mockServices, mockProjectNavLinks } from '../common/services/__mocks__/services.mock'; +import type { ProjectNavigationLink } from './links/types'; +import type { ExternalPageName } from './links/constants'; +import * as ml from '@kbn/default-nav-ml'; -const mockChromeNavLinks = jest.fn((): ChromeNavLink[] => []); -const mockChromeGetNavLinks = jest.fn(() => new BehaviorSubject(mockChromeNavLinks())); -const mockChromeNavLinksGet = jest.fn((id: string): ChromeNavLink | undefined => - mockChromeNavLinks().find((link) => link.id === id) -); -const mockChromeNavLinksHas = jest.fn((id: string): boolean => - mockChromeNavLinks().some((link) => link.id === id) -); - -const testServices = { - ...mockServices, - chrome: { - ...mockServices.chrome, - navLinks: { - ...mockServices.chrome.navLinks, - get: mockChromeNavLinksGet, - has: mockChromeNavLinksHas, - getNavLinks$: mockChromeGetNavLinks, - }, - }, -}; +jest.mock('@kbn/default-nav-ml'); const link1Id = 'link-1' as SecurityPageName; const link2Id = 'link-2' as SecurityPageName; +const link3Id = 'externalAppId:link-1' as ExternalPageName; const link1: ProjectNavigationLink = { id: link1Id, title: 'link 1' }; const link2: ProjectNavigationLink = { id: link2Id, title: 'link 2' }; +const link3: ProjectNavigationLink = { id: link3Id, title: 'link 3' }; const chromeNavLink1: ChromeNavLink = { id: `${APP_UI_ID}:${link1.id}`, @@ -53,20 +37,84 @@ const chromeNavLink2: ChromeNavLink = { url: '/link2', baseUrl: '', }; +const chromeNavLink3: ChromeNavLink = { + id: link3.id, + title: link3.title, + href: '/link3', + url: '/link3', + baseUrl: '', +}; +const chromeNavLinkMl1: ChromeNavLink = { + id: 'ml:subLink-1', + title: 'ML subLink 1', + href: '/ml/link1', + url: '/ml/link1', + baseUrl: '', +}; +const chromeNavLinkMl2: ChromeNavLink = { + id: 'ml:subLink-2', + title: 'ML subLink 2', + href: '/ml/link2', + url: '/ml/link2', + baseUrl: '', +}; +const defaultNavCategory1 = { + id: 'category_one', + title: 'ML Category1', +}; + +(ml as { defaultNavigation: unknown }).defaultNavigation = { + children: [ + { + id: 'root', + children: [ + { + link: chromeNavLinkMl1.id, + }, + ], + }, + { + ...defaultNavCategory1, + children: [ + { + title: 'Overridden ML SubLink 2', + link: chromeNavLinkMl2.id, + }, + ], + }, + ], +}; -const waitForDebounce = async () => new Promise((resolve) => setTimeout(resolve, 150)); +let chromeNavLinks: ChromeNavLink[] = []; +const mockChromeNavLinksGet = jest.fn((id: string): ChromeNavLink | undefined => + chromeNavLinks.find((link) => link.id === id) +); +const mockChromeNavLinksHas = jest.fn((id: string): boolean => + chromeNavLinks.some((link) => link.id === id) +); + +const testServices = { + ...mockServices, + chrome: { + ...mockServices.chrome, + navLinks: { + ...mockServices.chrome.navLinks, + get: mockChromeNavLinksGet, + has: mockChromeNavLinksHas, + }, + }, +}; describe('subscribeNavigationTree', () => { beforeEach(() => { jest.clearAllMocks(); - mockChromeNavLinks.mockReturnValue([chromeNavLink1, chromeNavLink2]); + chromeNavLinks = [chromeNavLink1, chromeNavLink2, chromeNavLink3]; }); it('should call serverless setNavigation', async () => { mockProjectNavLinks.mockReturnValueOnce([link1]); subscribeNavigationTree(testServices); - await waitForDebounce(); expect(testServices.serverless.setNavigation).toHaveBeenCalledWith({ navigationTree: [ @@ -89,16 +137,9 @@ describe('subscribeNavigationTree', () => { }); it('should call serverless setNavigation with external link', async () => { - const externalLink = { ...link1, appId: 'externalAppId' }; - const chromeNavLinkExpected = { - ...chromeNavLink1, - id: `${externalLink.appId}:${externalLink.id}`, - }; - mockChromeNavLinks.mockReturnValue([chromeNavLinkExpected]); - mockProjectNavLinks.mockReturnValueOnce([externalLink]); + mockProjectNavLinks.mockReturnValueOnce([link3]); subscribeNavigationTree(testServices); - await waitForDebounce(); expect(testServices.serverless.setNavigation).toHaveBeenCalledWith({ navigationTree: [ @@ -109,10 +150,10 @@ describe('subscribeNavigationTree', () => { breadcrumbStatus: 'hidden', children: [ { - id: chromeNavLinkExpected.id, - title: externalLink.title, - path: ['root', chromeNavLinkExpected.id], - deepLink: chromeNavLinkExpected, + id: chromeNavLink3.id, + title: chromeNavLink3.title, + path: ['root', chromeNavLink3.id], + deepLink: chromeNavLink3, }, ], }, @@ -124,7 +165,6 @@ describe('subscribeNavigationTree', () => { mockProjectNavLinks.mockReturnValueOnce([{ ...link1, links: [link2] }]); subscribeNavigationTree(testServices); - await waitForDebounce(); expect(testServices.serverless.setNavigation).toHaveBeenCalledWith({ navigationTree: [ @@ -154,47 +194,16 @@ describe('subscribeNavigationTree', () => { }); }); - it('should not call serverless setNavigation when projectNavLinks is empty', async () => { - mockProjectNavLinks.mockReturnValueOnce([]); - - subscribeNavigationTree(testServices); - await waitForDebounce(); - - expect(testServices.serverless.setNavigation).not.toHaveBeenCalled(); - }); - - it('should not call serverless setNavigation when chrome navLinks is empty', async () => { - mockChromeNavLinks.mockReturnValue([]); - mockProjectNavLinks.mockReturnValueOnce([link1]); - - subscribeNavigationTree(testServices); - await waitForDebounce(); - - expect(testServices.serverless.setNavigation).not.toHaveBeenCalled(); - }); - - it('should debounce updates', async () => { - const id = 'expectedId' as SecurityPageName; - const linkExpected = { ...link1, id }; - const chromeNavLinkExpected = { ...chromeNavLink1, id: `${APP_UI_ID}:${id}` }; - - const chromeGetNavLinks$ = new BehaviorSubject([chromeNavLink1]); - mockChromeGetNavLinks.mockReturnValue(chromeGetNavLinks$); - - mockChromeNavLinks.mockReturnValue([chromeNavLink1, chromeNavLink2, chromeNavLinkExpected]); - mockProjectNavLinks.mockReturnValueOnce([linkExpected]); + it('should add default nav for ML page', async () => { + const chromeNavLinkTest = { + ...chromeNavLink1, + id: `${APP_UI_ID}:${SecurityPageName.mlLanding}`, + }; + chromeNavLinks = [chromeNavLinkTest, chromeNavLinkMl1, chromeNavLinkMl2]; + mockProjectNavLinks.mockReturnValueOnce([{ ...link1, id: SecurityPageName.mlLanding }]); subscribeNavigationTree(testServices); - chromeGetNavLinks$.next([chromeNavLink1]); - chromeGetNavLinks$.next([chromeNavLink2]); - chromeGetNavLinks$.next([chromeNavLinkExpected]); - - expect(testServices.serverless.setNavigation).not.toHaveBeenCalled(); - - await waitForDebounce(); - - expect(testServices.serverless.setNavigation).toHaveBeenCalledTimes(1); expect(testServices.serverless.setNavigation).toHaveBeenCalledWith({ navigationTree: [ { @@ -204,10 +213,36 @@ describe('subscribeNavigationTree', () => { breadcrumbStatus: 'hidden', children: [ { - id: chromeNavLinkExpected.id, + id: chromeNavLinkTest.id, title: link1.title, - path: ['root', chromeNavLinkExpected.id], - deepLink: chromeNavLinkExpected, + path: ['root', chromeNavLinkTest.id], + deepLink: chromeNavLinkTest, + children: [ + { + id: chromeNavLinkMl1.id, + title: chromeNavLinkMl1.title, + path: ['root', chromeNavLinkTest.id, chromeNavLinkMl1.id], + deepLink: chromeNavLinkMl1, + }, + { + id: defaultNavCategory1.id, + title: defaultNavCategory1.title, + path: ['root', chromeNavLinkTest.id, defaultNavCategory1.id], + children: [ + { + id: chromeNavLinkMl2.id, + title: 'Overridden ML SubLink 2', + path: [ + 'root', + chromeNavLinkTest.id, + defaultNavCategory1.id, + chromeNavLinkMl2.id, + ], + deepLink: chromeNavLinkMl2, + }, + ], + }, + ], }, ], }, @@ -216,11 +251,10 @@ describe('subscribeNavigationTree', () => { }); it('should not include links that are not in the chrome navLinks', async () => { - mockChromeNavLinks.mockReturnValue([chromeNavLink2]); + chromeNavLinks = [chromeNavLink2]; mockProjectNavLinks.mockReturnValueOnce([link1, link2]); subscribeNavigationTree(testServices); - await waitForDebounce(); expect(testServices.serverless.setNavigation).toHaveBeenCalledWith({ navigationTree: [ @@ -247,14 +281,13 @@ describe('subscribeNavigationTree', () => { ...chromeNavLink1, id: `${APP_UI_ID}:${SecurityPageName.usersEvents}`, // userEvents link is blacklisted }; - mockChromeNavLinks.mockReturnValue([chromeNavLinkTest, chromeNavLink2]); + chromeNavLinks = [chromeNavLinkTest, chromeNavLink2]; mockProjectNavLinks.mockReturnValueOnce([ { ...link1, id: SecurityPageName.usersEvents }, link2, ]); subscribeNavigationTree(testServices); - await waitForDebounce(); expect(testServices.serverless.setNavigation).toHaveBeenCalledWith({ navigationTree: [ diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree.ts b/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree.ts index 82555ae54332f22..5f3f8552ad61727 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/navigation_tree.ts @@ -5,17 +5,20 @@ * 2.0. */ -import type { ChromeNavLinks, ChromeProjectNavigationNode } from '@kbn/core-chrome-browser'; -import { APP_UI_ID, SecurityPageName } from '@kbn/security-solution-plugin/common'; -import { combineLatest, skipWhile, debounceTime } from 'rxjs'; +import type { ChromeProjectNavigationNode, NodeDefinition } from '@kbn/core-chrome-browser'; +import { defaultNavigation as mlDefaultNav } from '@kbn/default-nav-ml'; +import { defaultNavigation as devToolsDefaultNav } from '@kbn/default-nav-devtools'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; import type { Services } from '../common/services'; -import type { ProjectNavigationLink } from './links/types'; +import type { ProjectNavigationLink, ProjectPageName } from './links/types'; +import { getNavLinkIdFromProjectPageName } from './links/util'; +import { ExternalPageName } from './links/constants'; // We need to hide breadcrumbs for some pages (tabs) because they appear duplicated. // These breadcrumbs are incorrectly processed as trailing breadcrumbs in SecuritySolution, because of `SpyRoute` architecture limitations. // They are navLinks tree with a SecurityPageName, so they should be treated as leading breadcrumbs in ESS as well. // TODO: Improve the breadcrumbs logic in `use_breadcrumbs_nav` to avoid this workaround. -const HIDDEN_BREADCRUMBS = new Set([ +const HIDDEN_BREADCRUMBS = new Set([ SecurityPageName.networkDns, SecurityPageName.networkHttp, SecurityPageName.networkTls, @@ -33,54 +36,109 @@ const HIDDEN_BREADCRUMBS = new Set([ ]); export const subscribeNavigationTree = (services: Services): void => { - const { chrome, serverless, getProjectNavLinks$ } = services; + const { serverless, getProjectNavLinks$ } = services; - combineLatest([ - getProjectNavLinks$().pipe(skipWhile((navLink) => navLink.length === 0)), - chrome.navLinks.getNavLinks$().pipe(skipWhile((chromeNavLinks) => chromeNavLinks.length === 0)), - ]) - .pipe(debounceTime(100)) // avoid multiple calls in a short time - .subscribe(([projectNavLinks]) => { - // The root link is temporary until the issue about having multiple links at first level is solved. - // TODO: Assign the navigationTree nodes when the issue is solved: - // const navigationTree = formatChromeProjectNavNodes(chrome.navLinks, projectNavLinks), - const navigationTree: ChromeProjectNavigationNode[] = [ - { - id: 'root', - title: 'Root', - path: ['root'], - breadcrumbStatus: 'hidden', - children: formatChromeProjectNavNodes(chrome.navLinks, projectNavLinks, ['root']), - }, - ]; - serverless.setNavigation({ navigationTree }); - }); + const formatChromeProjectNavNodes = getFormatChromeProjectNavNodes(services); + + // projectNavLinks$ updates when chrome.navLinks changes, no need to subscribe chrome.navLinks.getNavLinks$() again. + getProjectNavLinks$().subscribe((projectNavLinks) => { + // TODO: The root link is temporary until the Platform bug having multiple links at first level is solved. + // Assign using the following line when the issue is solved: + // const navigationTree = formatChromeProjectNavNodes(chrome.navLinks, projectNavLinks), + const navigationTree: ChromeProjectNavigationNode[] = [ + { + id: 'root', + title: 'Root', + path: ['root'], + breadcrumbStatus: 'hidden', + children: formatChromeProjectNavNodes(projectNavLinks, ['root']), + }, + ]; + serverless.setNavigation({ navigationTree }); + }); }; -const formatChromeProjectNavNodes = ( - chromeNavLinks: ChromeNavLinks, - projectNavLinks: ProjectNavigationLink[], - path: string[] = [] -): ChromeProjectNavigationNode[] => - projectNavLinks.reduce((navNodes, navLink) => { - const { id: deepLinkId, appId = APP_UI_ID, links, title } = navLink; +// Closure to access the up to date chrome.navLinks from services +export const getFormatChromeProjectNavNodes = (services: Services) => { + const formatChromeProjectNavNodes = ( + projectNavLinks: ProjectNavigationLink[], + path: string[] = [] + ): ChromeProjectNavigationNode[] => { + const { chrome } = services; + return projectNavLinks.reduce((navNodes, navLink) => { + const { id, title, links } = navLink; + const navLinkId = getNavLinkIdFromProjectPageName(id); + + if (chrome.navLinks.has(navLinkId)) { + const breadcrumbHidden = HIDDEN_BREADCRUMBS.has(id); + const link: ChromeProjectNavigationNode = { + id: navLinkId, + title, + path: [...path, navLinkId], + deepLink: chrome.navLinks.get(navLinkId), + ...(breadcrumbHidden && { breadcrumbStatus: 'hidden' }), + }; + // check default navigation for children + const defaultChildrenNav = getDefaultChildrenNav(id, link); + if (defaultChildrenNav) { + link.children = defaultChildrenNav; + } else if (links?.length) { + link.children = formatChromeProjectNavNodes(links, link.path); + } + navNodes.push(link); + } + return navNodes; + }, []); + }; - const id = deepLinkId ? `${appId}:${deepLinkId}` : appId; + const getDefaultChildrenNav = ( + id: ProjectPageName, + link: ChromeProjectNavigationNode + ): ChromeProjectNavigationNode[] | undefined => { + if (id === SecurityPageName.mlLanding) { + return processDefaultNav(mlDefaultNav.children, link.path); + } + if (id === ExternalPageName.devToolsRoot) { + return processDefaultNav(devToolsDefaultNav.children, link.path); + } + return undefined; + }; - if (chromeNavLinks.has(id)) { - const breadcrumbHidden = appId === APP_UI_ID && HIDDEN_BREADCRUMBS.has(deepLinkId); - const link: ChromeProjectNavigationNode = { + const processDefaultNav = ( + children: NodeDefinition[], + path: string[] + ): ChromeProjectNavigationNode[] => { + const { chrome } = services; + return children.reduce((navNodes, node) => { + const id = node.id ?? node.link; + if (!id) { + return navNodes; + } + if (id === 'root') { + if (node.children) { + navNodes.push(...processDefaultNav(node.children, path)); + } + return navNodes; + } + const navNode: ChromeProjectNavigationNode = { id, - title, + title: node.title || '', path: [...path, id], - deepLink: chromeNavLinks.get(id), - ...(breadcrumbHidden && { breadcrumbStatus: 'hidden' }), }; - - if (links?.length) { - link.children = formatChromeProjectNavNodes(chromeNavLinks, links, link.path); + if (chrome.navLinks.has(id)) { + const deepLink = chrome.navLinks.get(id); + navNode.deepLink = deepLink; + if (!navNode.title) { + navNode.title = deepLink?.title || ''; + } } - navNodes.push(link); - } - return navNodes; - }, []); + if (node.children?.length) { + navNode.children = processDefaultNav(node.children, navNode.path); + } + navNodes.push(navNode); + return navNodes; + }, []); + }; + + return formatChromeProjectNavNodes; +}; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/categories.ts b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/categories.ts index 68a3cb01f87b59f..62661aedf6bf167 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/categories.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/categories.ts @@ -5,8 +5,12 @@ * 2.0. */ -import { LinkCategoryType, type SeparatorLinkCategory } from '@kbn/security-solution-side-nav'; -import { SecurityPageName } from '@kbn/security-solution-plugin/common'; +import { + SecurityPageName, + LinkCategoryType, + type SeparatorLinkCategory, +} from '@kbn/security-solution-navigation'; +import { ExternalPageName } from '../links/constants'; export const CATEGORIES: SeparatorLinkCategory[] = [ { @@ -33,4 +37,8 @@ export const CATEGORIES: SeparatorLinkCategory[] = [ type: LinkCategoryType.separator, linkIds: [SecurityPageName.rulesLanding], }, + { + type: LinkCategoryType.separator, + linkIds: [SecurityPageName.mlLanding, ExternalPageName.devToolsRoot], + }, ]; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/index.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/index.tsx index c749131300b5d94..6ee90bc3a516472 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/index.tsx +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/index.tsx @@ -6,15 +6,9 @@ */ import React from 'react'; -import type { SideNavComponent } from '@kbn/core-chrome-browser/src/project_navigation'; +import type { SideNavComponent } from '@kbn/core-chrome-browser'; import { SecuritySideNavigation } from './lazy'; -import { KibanaServicesProvider, type Services } from '../../common/services'; +import { withServicesProvider, type Services } from '../../common/services'; export const getSecuritySideNavComponent = (services: Services): SideNavComponent => - function SecuritySideNavComponent() { - return ( - - - - ); - }; + React.memo(withServicesProvider(SecuritySideNavigation, services)); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/lazy.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/lazy.tsx index b7bda570000d8ed..33af766372dec2c 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/lazy.tsx +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/lazy.tsx @@ -6,11 +6,12 @@ */ import React, { lazy, Suspense } from 'react'; import { EuiLoadingSpinner } from '@elastic/eui'; +import type { SideNavComponent } from '@kbn/core-chrome-browser'; const SecuritySideNavigationLazy = lazy(() => import('./side_navigation')); -export const SecuritySideNavigation = () => ( +export const SecuritySideNavigation: SideNavComponent = (props) => ( }> - + ); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.test.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.test.tsx index 1df7e2ca3008f4a..f12664c02c3eae6 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.test.tsx +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.test.tsx @@ -7,15 +7,18 @@ import React from 'react'; import { render } from '@testing-library/react'; +import { APP_UI_ID } from '@kbn/security-solution-plugin/common'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; import { SecuritySideNavigation } from './side_navigation'; -import { useSideNavItems, useSideNavSelectedId } from './use_side_nav_items'; -import { SecurityPageName } from '@kbn/security-solution-plugin/common'; -import { ServicesWrapper } from '../../common/__mocks__/services.mock'; +import { useSideNavItems } from './use_side_nav_items'; +import type { ChromeProjectNavigationNode } from '@kbn/core-chrome-browser'; +import { ExternalPageName } from '../links/constants'; +import { I18nProvider } from '@kbn/i18n-react'; jest.mock('./use_side_nav_items'); +jest.mock('../../common/services'); const mockUseSideNavItems = useSideNavItems as jest.Mock; -const mockUseSideNavSelectedId = useSideNavSelectedId as jest.Mock; const mockSolutionSideNav = jest.fn((_props: unknown) =>
); jest.mock('@kbn/security-solution-side-nav', () => ({ @@ -46,7 +49,6 @@ const sideNavItems = [ ]; mockUseSideNavItems.mockReturnValue(sideNavItems); -mockUseSideNavSelectedId.mockReturnValue(SecurityPageName.alerts); describe('SecuritySideNavigation', () => { beforeEach(() => { @@ -55,22 +57,28 @@ describe('SecuritySideNavigation', () => { it('should render loading when not items received', () => { mockUseSideNavItems.mockReturnValueOnce([]); - const component = render(, { wrapper: ServicesWrapper }); + const component = render(, { + wrapper: I18nProvider, + }); expect(component.queryByTestId('sideNavLoader')).toBeInTheDocument(); }); it('should not render loading when items received', () => { - const component = render(, { wrapper: ServicesWrapper }); + const component = render(, { + wrapper: I18nProvider, + }); expect(component.queryByTestId('sideNavLoader')).not.toBeInTheDocument(); }); it('should render the SideNav when items received', () => { - const component = render(, { wrapper: ServicesWrapper }); + const component = render(, { + wrapper: I18nProvider, + }); expect(component.queryByTestId('solutionSideNav')).toBeInTheDocument(); }); it('should pass item props to the SolutionSideNav component', () => { - render(, { wrapper: ServicesWrapper }); + render(, { wrapper: I18nProvider }); expect(mockSolutionSideNav).toHaveBeenCalledWith( expect.objectContaining({ @@ -79,8 +87,43 @@ describe('SecuritySideNavigation', () => { ); }); - it('should selectedId the SolutionSideNav component', () => { - render(, { wrapper: ServicesWrapper }); + it('should have empty selectedId the SolutionSideNav component', () => { + render(, { wrapper: I18nProvider }); + + expect(mockSolutionSideNav).toHaveBeenCalledWith( + expect.objectContaining({ + selectedId: '', + }) + ); + }); + + it('should have root external selectedId the SolutionSideNav component', () => { + const activeNodes = [[{ id: 'dev_tools' }]] as ChromeProjectNavigationNode[][]; + render(, { wrapper: I18nProvider }); + + expect(mockSolutionSideNav).toHaveBeenCalledWith( + expect.objectContaining({ + selectedId: ExternalPageName.devToolsRoot, + }) + ); + }); + + it('should have external page selectedId the SolutionSideNav component', () => { + const activeNodes = [[{ id: `ml:overview` }]] as ChromeProjectNavigationNode[][]; + render(, { wrapper: I18nProvider }); + + expect(mockSolutionSideNav).toHaveBeenCalledWith( + expect.objectContaining({ + selectedId: ExternalPageName.mlOverview, + }) + ); + }); + + it('should internal selectedId the SolutionSideNav component', () => { + const activeNodes = [ + [{ id: `${APP_UI_ID}:${SecurityPageName.alerts}` }], + ] as ChromeProjectNavigationNode[][]; + render(, { wrapper: I18nProvider }); expect(mockSolutionSideNav).toHaveBeenCalledWith( expect.objectContaining({ diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.tsx index 5ba20e26cac2148..45d31875cc0ea0f 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.tsx +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/side_navigation.tsx @@ -5,20 +5,29 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { EuiLoadingSpinner, useEuiTheme } from '@elastic/eui'; +import type { SideNavComponent } from '@kbn/core-chrome-browser'; import { SolutionNav } from '@kbn/shared-ux-page-solution-nav'; import { SolutionSideNav } from '@kbn/security-solution-side-nav'; -import { useSideNavItems, useSideNavSelectedId } from './use_side_nav_items'; +import { useSideNavItems } from './use_side_nav_items'; import { CATEGORIES } from './categories'; +import { getProjectPageNameFromNavLinkId } from '../links/util'; -export const SecuritySideNavigation: React.FC = () => { +export const SecuritySideNavigation: SideNavComponent = React.memo(function SecuritySideNavigation({ + activeNodes: [activeChromeNodes], +}) { const { euiTheme } = useEuiTheme(); const items = useSideNavItems(); - const selectedId = useSideNavSelectedId(items); const isLoading = items.length === 0; + const selectedId = useMemo(() => { + // TODO: change the following line to `const mainNode = activeChromeNodes[0]` when the root node is no longer present + const mainNode = activeChromeNodes?.find((node) => node.id !== 'root'); + return mainNode ? getProjectPageNameFromNavLinkId(mainNode.id) : ''; + }, [activeChromeNodes]); + return isLoading ? ( ) : ( @@ -39,7 +48,7 @@ export const SecuritySideNavigation: React.FC = () => { /> ); -}; +}); // eslint-disable-next-line import/no-default-export export default SecuritySideNavigation; diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.test.tsx b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.test.tsx index 2145961e36aa5dc..9f6f93cd51c93e7 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.test.tsx +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.test.tsx @@ -6,11 +6,11 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { useSideNavItems, useSideNavSelectedId } from './use_side_nav_items'; -import { SecurityPageName } from '@kbn/security-solution-plugin/common'; -import { mockServices, mockProjectNavLinks } from '../../common/__mocks__/services.mock'; +import { useSideNavItems } from './use_side_nav_items'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; +import { mockServices, mockProjectNavLinks } from '../../common/services/__mocks__/services.mock'; -jest.mock('../../common/hooks/use_link_props'); +jest.mock('@kbn/security-solution-navigation/src/navigation'); jest.mock('../../common/services'); const mockUseLocation = jest.fn(() => ({ pathname: '/' })); @@ -45,14 +45,12 @@ describe('useSideNavItems', () => { id: SecurityPageName.alerts, label: 'Alerts', position: 'top', - href: expect.any(String), onClick: expect.any(Function), }, { id: SecurityPageName.case, label: 'Cases', position: 'top', - href: expect.any(String), onClick: expect.any(Function), }, ]); @@ -74,13 +72,11 @@ describe('useSideNavItems', () => { id: SecurityPageName.dashboards, label: 'Dashboards', position: 'top', - href: expect.any(String), onClick: expect.any(Function), items: [ { id: SecurityPageName.detectionAndResponse, label: 'Detection & Response', - href: expect.any(String), onClick: expect.any(Function), }, ], @@ -105,7 +101,6 @@ describe('useSideNavItems', () => { id: SecurityPageName.landing, label: 'Get Started', position: 'bottom', - href: expect.any(String), onClick: expect.any(Function), iconType: 'launch', appendSeparator: true, @@ -113,79 +108,3 @@ describe('useSideNavItems', () => { ]); }); }); - -describe('useSideNavSelectedId', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('should return empty string when no item selected', async () => { - const items = [ - { - id: SecurityPageName.dashboards, - label: 'Dashboards', - href: '/app/security/dashboards', - onClick: jest.fn(), - }, - { - id: SecurityPageName.alerts, - label: 'Alerts', - href: '/app/security/alerts', - onClick: jest.fn(), - }, - ]; - - const { result } = renderHook(useSideNavSelectedId, { initialProps: items }); - - const selectedId = result.current; - expect(selectedId).toEqual(''); - }); - - it('should return the item with path selected', async () => { - mockUseLocation.mockReturnValueOnce({ pathname: '/app/security/alerts' }); - const items = [ - { - id: SecurityPageName.dashboards, - label: 'Dashboards', - href: '/app/security/dashboards', - onClick: jest.fn(), - }, - { - id: SecurityPageName.alerts, - label: 'Alerts', - href: '/app/security/alerts', - onClick: jest.fn(), - }, - ]; - - const { result } = renderHook(useSideNavSelectedId, { initialProps: items }); - - const selectedId = result.current; - expect(selectedId).toEqual(SecurityPageName.alerts); - }); - - it('should return the main item when nested path selected', async () => { - mockUseLocation.mockReturnValueOnce({ pathname: '/app/security/detection_response' }); - const items = [ - { - id: SecurityPageName.dashboards, - label: 'Dashboards', - href: '/app/security/dashboards', - onClick: jest.fn(), - items: [ - { - id: SecurityPageName.detectionAndResponse, - label: 'Detection & Response', - href: '/app/security/detection_response', - onClick: jest.fn(), - }, - ], - }, - ]; - - const { result } = renderHook(useSideNavSelectedId, { initialProps: items }); - - const selectedId = result.current; - expect(selectedId).toEqual(SecurityPageName.dashboards); - }); -}); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.ts b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.ts index 779dd86764d7446..766178dbbb09671 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/side_navigation/use_side_nav_items.ts @@ -6,18 +6,14 @@ */ import { useMemo } from 'react'; -import { matchPath, useLocation } from 'react-router-dom'; -import { SecurityPageName } from '@kbn/security-solution-plugin/common'; +import { SecurityPageName, type NavigationLink } from '@kbn/security-solution-navigation'; +import { useGetLinkProps, type GetLinkProps } from '@kbn/security-solution-navigation/links'; import { SolutionSideNavItemPosition, type SolutionSideNavItem, } from '@kbn/security-solution-side-nav'; -import { useKibana } from '../../common/services'; -import { type GetLinkProps, useGetLinkProps } from '../../common/hooks/use_link_props'; import { useNavLinks } from '../../common/hooks/use_nav_links'; -type NavigationLink = ReturnType[number]; - const isBottomNavItem = (id: string) => id === SecurityPageName.landing || id === SecurityPageName.administration; const isGetStartedNavItem = (id: string) => id === SecurityPageName.landing; @@ -32,7 +28,7 @@ const formatLink = (navLink: NavigationLink, getLinkProps: GetLinkProps): Soluti position: isBottomNavItem(navLink.id) ? SolutionSideNavItemPosition.bottom : SolutionSideNavItemPosition.top, - ...getLinkProps({ deepLinkId: navLink.id }), + ...getLinkProps({ id: navLink.id }), ...(navLink.categories?.length && { categories: navLink.categories }), ...(navLink.links?.length && { items: navLink.links.reduce((acc, current) => { @@ -43,7 +39,7 @@ const formatLink = (navLink: NavigationLink, getLinkProps: GetLinkProps): Soluti iconType: current.sideNavIcon, isBeta: current.isBeta, betaOptions: current.betaOptions, - ...getLinkProps({ deepLinkId: current.id }), + ...getLinkProps({ id: current.id }), }); } return acc; @@ -62,30 +58,10 @@ const formatGetStartedLink = ( label: navLink.title, iconType: navLink.sideNavIcon, position: SolutionSideNavItemPosition.bottom, - ...getLinkProps({ deepLinkId: navLink.id }), + ...getLinkProps({ id: navLink.id }), appendSeparator: true, }); -// DFS for the sideNavItem matching the current `pathname`, returns all item hierarchy when found -const findItemsByPath = ( - sideNavItems: SolutionSideNavItem[], - pathname: string -): SolutionSideNavItem[] => { - for (const sideNavItem of sideNavItems) { - if (sideNavItem.items?.length) { - const found = findItemsByPath(sideNavItem.items, pathname); - if (found.length) { - found.unshift(sideNavItem); - return found; - } - } - if (matchPath(pathname, { path: sideNavItem.href })) { - return [sideNavItem]; - } - } - return []; -}; - /** * Returns all the formatted SideNavItems, including external links */ @@ -93,7 +69,7 @@ export const useSideNavItems = (): SolutionSideNavItem[] => { const navLinks = useNavLinks(); const getLinkProps = useGetLinkProps(); - const securitySideNavItems = useMemo( + return useMemo( () => navLinks.reduce((items, navLink) => { if (navLink.disabled) { @@ -108,45 +84,4 @@ export const useSideNavItems = (): SolutionSideNavItem[] => { }, []), [getLinkProps, navLinks] ); - - const sideNavItems = useAddExternalSideNavItems(securitySideNavItems); - - return sideNavItems; -}; - -/** - * @param securitySideNavItems the sideNavItems for Security pages - * @returns sideNavItems with Security and external links - */ -const useAddExternalSideNavItems = (securitySideNavItems: SolutionSideNavItem[]) => { - const sideNavItemsWithExternals = useMemo( - () => [ - ...securitySideNavItems, - // TODO: add external links. e.g.: - // { - // id: 'ml', - // label: 'Machine Learning Jobs', - // ...getLinkProps({ appId: 'ml', path: '/jobs' }), - // links: [...] - // }, - ], - [securitySideNavItems] - ); - - return sideNavItemsWithExternals; -}; - -/** - * Returns the selected item id, which is the root item in the links hierarchy - */ -export const useSideNavSelectedId = (sideNavItems: SolutionSideNavItem[]): string => { - const { http } = useKibana().services; - const { pathname } = useLocation(); - - const selectedId: string = useMemo(() => { - const [rootNavItem] = findItemsByPath(sideNavItems, http.basePath.prepend(pathname)); - return rootNavItem?.id ?? ''; - }, [sideNavItems, pathname, http]); - - return selectedId; }; diff --git a/x-pack/plugins/security_solution_serverless/public/pages/machine_learning.tsx b/x-pack/plugins/security_solution_serverless/public/pages/machine_learning.tsx new file mode 100644 index 000000000000000..72c8b1c588ebb80 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/pages/machine_learning.tsx @@ -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 React from 'react'; +import { LandingLinksIconsCategories } from '@kbn/security-solution-navigation/landing_links'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; +import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; +import { EuiPageHeader, EuiSpacer } from '@elastic/eui'; +import { useNavLink } from '../common/hooks/use_nav_links'; + +export const MachineLearningRoute: React.FC = () => { + const link = useNavLink(SecurityPageName.mlLanding); + const { links = [], categories = [], title, landingIcon } = link ?? {}; + return ( + + + + + + + + ); +}; + +// eslint-disable-next-line import/no-default-export +export default MachineLearningRoute; diff --git a/x-pack/plugins/security_solution_serverless/public/pages/routes.tsx b/x-pack/plugins/security_solution_serverless/public/pages/routes.tsx new file mode 100644 index 000000000000000..e3a79fd3c922122 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/pages/routes.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { lazy, Suspense } from 'react'; +import { EuiLoadingSpinner } from '@elastic/eui'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; +import type { RouteProps } from 'react-router-dom'; +import { withServicesProvider, type Services } from '../common/services'; +import { SecurityPagePath } from '../navigation/links/constants'; + +const withSuspense = (Component: React.ComponentType): React.FC => + function LazyPageWithSuspense(props) { + return ( + }> + + + ); + }; + +const MachineLearningPageLazy = lazy(() => import('./machine_learning')); +const MachineLearningPage = withSuspense(MachineLearningPageLazy); + +// Sets the project specific routes for Serverless as extra routes in the Security Solution plugin +export const setRoutes = (services: Services) => { + const projectRoutes: RouteProps[] = [ + { + path: SecurityPagePath[SecurityPageName.mlLanding], + component: withServicesProvider(MachineLearningPage, services), + }, + ]; + services.securitySolution.setExtraRoutes(projectRoutes); +}; diff --git a/x-pack/plugins/security_solution_serverless/public/plugin.ts b/x-pack/plugins/security_solution_serverless/public/plugin.ts index 307a438c6e9c3a5..ce3ea5b7ef66fb3 100644 --- a/x-pack/plugins/security_solution_serverless/public/plugin.ts +++ b/x-pack/plugins/security_solution_serverless/public/plugin.ts @@ -16,8 +16,9 @@ import type { ServerlessSecurityPublicConfig, } from './types'; import { registerUpsellings } from './upselling'; -import { createServices } from './common/services'; -import { setServerlessNavigation } from './navigation'; +import { createServices } from './common/services/create_services'; +import { configureNavigation } from './navigation'; +import { setRoutes } from './pages/routes'; export class SecuritySolutionServerlessPlugin implements @@ -53,7 +54,8 @@ export class SecuritySolutionServerlessPlugin securitySolution.setGetStartedPage(getSecurityGetStartedComponent(services, productTypes)); - setServerlessNavigation(services); + configureNavigation(services); + setRoutes(services); return {}; } diff --git a/x-pack/plugins/security_solution_serverless/public/upselling/register_upsellings.tsx b/x-pack/plugins/security_solution_serverless/public/upselling/register_upsellings.tsx index a5567ccf0e57b94..a2ff9066f644c04 100644 --- a/x-pack/plugins/security_solution_serverless/public/upselling/register_upsellings.tsx +++ b/x-pack/plugins/security_solution_serverless/public/upselling/register_upsellings.tsx @@ -5,7 +5,8 @@ * 2.0. */ import React, { lazy } from 'react'; -import { SecurityPageName, AppFeatureKey } from '@kbn/security-solution-plugin/common'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; +import { AppFeatureKey } from '@kbn/security-solution-plugin/common'; import type { UpsellingService, PageUpsellings, diff --git a/x-pack/plugins/security_solution_serverless/tsconfig.json b/x-pack/plugins/security_solution_serverless/tsconfig.json index cce3249926fee32..b69dbcb5b189a4f 100644 --- a/x-pack/plugins/security_solution_serverless/tsconfig.json +++ b/x-pack/plugins/security_solution_serverless/tsconfig.json @@ -22,6 +22,9 @@ "@kbn/serverless", "@kbn/shared-ux-page-solution-nav", "@kbn/security-solution-side-nav", + "@kbn/security-solution-navigation", + "@kbn/default-nav-ml", + "@kbn/default-nav-devtools", "@kbn/kibana-react-plugin", "@kbn/core-chrome-browser", "@kbn/i18n-react", diff --git a/yarn.lock b/yarn.lock index 93a8c8f47ace03c..3fa41c07ccd7135 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5066,6 +5066,10 @@ version "0.0.0" uid "" +"@kbn/security-solution-navigation@link:x-pack/packages/security-solution/navigation": + version "0.0.0" + uid "" + "@kbn/security-solution-plugin@link:x-pack/plugins/security_solution": version "0.0.0" uid "" From 586afe9f27ed326862f3b1f52d2664bd25e6eff1 Mon Sep 17 00:00:00 2001 From: Luke G <11671118+lgestc@users.noreply.github.com> Date: Tue, 25 Jul 2023 23:17:36 +0200 Subject: [PATCH 29/29] [Serverless] #7099 Move install prepackaged timelines schema (#162314) ## Summary This PR moves the last remaining timeline api schema to a common location as per https://github.com/elastic/security-team/issues/7099 ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../common/api/timeline/index.ts | 1 + .../install_prepackaged_timelines.ts | 19 +++++++++++++++++++ ...ebuilt_rules_and_timelines_status_route.ts | 6 ++---- .../install_prepackaged_timelines/index.ts | 3 ++- .../timeline/utils/check_timelines_status.ts | 19 ++++--------------- 5 files changed, 28 insertions(+), 20 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/api/timeline/install_prepackaged_timelines/install_prepackaged_timelines.ts diff --git a/x-pack/plugins/security_solution/common/api/timeline/index.ts b/x-pack/plugins/security_solution/common/api/timeline/index.ts index 4a0858b72fea312..26a4a46f07a61e2 100644 --- a/x-pack/plugins/security_solution/common/api/timeline/index.ts +++ b/x-pack/plugins/security_solution/common/api/timeline/index.ts @@ -19,3 +19,4 @@ export * from './patch_timelines/patch_timelines_schema'; export * from './persist_favorite/persist_favorite_schema'; export * from './persist_note/persist_note_route'; export * from './pinned_events/pinned_events_route'; +export * from './install_prepackaged_timelines/install_prepackaged_timelines'; diff --git a/x-pack/plugins/security_solution/common/api/timeline/install_prepackaged_timelines/install_prepackaged_timelines.ts b/x-pack/plugins/security_solution/common/api/timeline/install_prepackaged_timelines/install_prepackaged_timelines.ts new file mode 100644 index 000000000000000..0d9b2d3e81121aa --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/timeline/install_prepackaged_timelines/install_prepackaged_timelines.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 * as rt from 'io-ts'; + +import { unionWithNullType } from '../../../utility_types'; +import { ImportTimelinesSchemaRt, TimelineSavedToReturnObjectRuntimeType } from '..'; + +export const checkTimelineStatusRt = rt.type({ + timelinesToInstall: rt.array(unionWithNullType(ImportTimelinesSchemaRt)), + timelinesToUpdate: rt.array(unionWithNullType(ImportTimelinesSchemaRt)), + prepackagedTimelines: rt.array(unionWithNullType(TimelineSavedToReturnObjectRuntimeType)), +}); + +export type CheckTimelineStatusRt = rt.TypeOf; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts index 290db5ad7d5b287..f6c69ccd8a88b9c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/api/get_prebuilt_rules_and_timelines_status/get_prebuilt_rules_and_timelines_status_route.ts @@ -7,6 +7,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { validate } from '@kbn/securitysolution-io-ts-utils'; +import { checkTimelineStatusRt } from '../../../../../../common/api/timeline'; import { buildSiemResponse } from '../../../routes/utils'; import type { SetupPlugins } from '../../../../../plugin'; import type { SecuritySolutionPluginRouter } from '../../../../../types'; @@ -24,10 +25,7 @@ import { createPrebuiltRuleAssetsClient } from '../../logic/rule_assets/prebuilt import { rulesToMap } from '../../logic/utils'; import { buildFrameworkRequest } from '../../../../timeline/utils/common'; -import { - checkTimelinesStatus, - checkTimelineStatusRt, -} from '../../../../timeline/utils/check_timelines_status'; +import { checkTimelinesStatus } from '../../../../timeline/utils/check_timelines_status'; export const getPrebuiltRulesAndTimelinesStatusRoute = ( router: SecuritySolutionPluginRouter, diff --git a/x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts b/x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts index 82220fdcb42e4aa..718257ac89321d0 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/routes/prepackaged_timelines/install_prepackaged_timelines/index.ts @@ -7,6 +7,7 @@ import { transformError } from '@kbn/securitysolution-es-utils'; import { validate } from '@kbn/securitysolution-io-ts-utils'; +import { checkTimelineStatusRt } from '../../../../../../common/api/timeline'; import type { SecuritySolutionPluginRouter } from '../../../../../types'; import { TIMELINE_PREPACKAGED_URL } from '../../../../../../common/constants'; @@ -18,7 +19,7 @@ import { buildSiemResponse } from '../../../../detection_engine/routes/utils'; import { installPrepackagedTimelines } from './helpers'; -import { checkTimelinesStatus, checkTimelineStatusRt } from '../../../utils/check_timelines_status'; +import { checkTimelinesStatus } from '../../../utils/check_timelines_status'; import { buildFrameworkRequest } from '../../../utils/common'; diff --git a/x-pack/plugins/security_solution/server/lib/timeline/utils/check_timelines_status.ts b/x-pack/plugins/security_solution/server/lib/timeline/utils/check_timelines_status.ts index d1b9ecec79ecbeb..a5e88a3ea04d516 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/utils/check_timelines_status.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/utils/check_timelines_status.ts @@ -6,29 +6,18 @@ */ import path, { join, resolve } from 'path'; -import * as rt from 'io-ts'; -import type { TimelineSavedObject, ImportTimelinesSchema } from '../../../../common/api/timeline'; -import { - TimelineSavedToReturnObjectRuntimeType, - ImportTimelinesSchemaRt, +import type { + CheckTimelineStatusRt, + TimelineSavedObject, + ImportTimelinesSchema, } from '../../../../common/api/timeline'; -import { unionWithNullType } from '../../../../common/utility_types'; - import type { FrameworkRequest } from '../../framework'; import { getExistingPrepackagedTimelines } from '../saved_object/timelines'; import { loadData, getReadables } from './common'; -export const checkTimelineStatusRt = rt.type({ - timelinesToInstall: rt.array(unionWithNullType(ImportTimelinesSchemaRt)), - timelinesToUpdate: rt.array(unionWithNullType(ImportTimelinesSchemaRt)), - prepackagedTimelines: rt.array(unionWithNullType(TimelineSavedToReturnObjectRuntimeType)), -}); - -export type CheckTimelineStatusRt = rt.TypeOf; - export const getTimelinesToUpdate = ( timelinesFromFileSystem: ImportTimelinesSchema[], installedTimelines: TimelineSavedObject[]