From 7c7fbc70cd081bfe9b5dbdbe90e6773c1e3772d5 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 20 Apr 2020 11:12:17 +0200 Subject: [PATCH 01/17] [Uptime] Refactor folder structure (#63442) * update structure * update connected structure * update connected structure * update code structure * update types * update imports * update folder * update trans * fixed snapshot * updated code * refacto monitor list container * update types Co-authored-by: Elastic Machine --- .../common/constants/chart_format_limits.ts | 2 +- .../common/constants/context_defaults.ts | 2 +- .../plugins/uptime/common/graphql/types.ts | 0 .../uptime/common/runtime_types/common.ts | 1 - .../plugins/uptime/common/types/index.ts | 4 + .../plugins/uptime/public/apps/plugin.ts | 14 +- .../__snapshots__/location_link.test.tsx.snap | 0 .../uptime_date_picker.test.tsx.snap | 0 .../__tests__/location_link.test.tsx | 0 .../__tests__/uptime_date_picker.test.tsx | 0 .../chart_empty_state.test.tsx.snap | 0 .../__snapshots__/chart_wrapper.test.tsx.snap | 0 .../__snapshots__/donut_chart.test.tsx.snap | 0 .../donut_chart_legend.test.tsx.snap | 0 .../donut_chart_legend_row.test.tsx.snap | 0 .../duration_charts.test.tsx.snap | 1 - .../monitor_bar_series.test.tsx.snap | 0 .../ping_histogram.test.tsx.snap | 0 .../__tests__/chart_empty_state.test.tsx | 0 .../charts/__tests__/chart_wrapper.test.tsx | 2 +- .../charts/__tests__/donut_chart.test.tsx | 0 .../__tests__/donut_chart_legend.test.tsx | 0 .../__tests__/donut_chart_legend_row.test.tsx | 0 .../charts/__tests__/duration_charts.test.tsx | 1 - .../charts/__tests__/get_tick_format.test.ts | 0 .../__tests__/monitor_bar_series.test.tsx | 0 .../charts/__tests__/ping_histogram.test.tsx | 0 .../charts/annotation_tooltip.tsx | 0 .../charts/chart_empty_state.tsx | 0 .../charts/chart_wrapper/chart_wrapper.tsx | 0 .../charts/chart_wrapper/index.ts | 0 .../charts/donut_chart.tsx | 0 .../charts/donut_chart_legend.tsx | 0 .../charts/donut_chart_legend_row.tsx | 0 .../common/charts/duration_chart.tsx | 122 ++++++++++++++ .../charts/duration_line_bar_list.tsx | 0 .../charts/duration_line_series_list.tsx | 2 +- .../charts/get_tick_format.ts | 0 .../{functional => common}/charts/index.ts | 0 .../charts/monitor_bar_series.tsx | 0 .../charts/ping_histogram.tsx | 0 .../responsive_wrapper.test.tsx.snap | 0 .../__tests__/responsive_wrapper.test.tsx | 0 .../{ => common}/higher_order/index.ts | 0 .../higher_order/responsive_wrapper.tsx | 0 .../location_link.tsx | 0 .../uptime_date_picker.tsx | 2 +- .../connected/charts/ping_histogram.tsx | 82 --------- .../connected/charts/snapshot_container.tsx | 93 ----------- .../public/components/connected/index.ts | 19 --- .../monitor/status_bar_container.tsx | 71 -------- .../monitor/status_details_container.tsx | 63 ------- .../functional/charts/duration_chart.tsx | 155 ------------------ .../public/components/functional/index.ts | 20 --- .../monitor_status_bar/index.ts | 8 - .../components/functional/search_schema.ts | 17 -- .../monitor_charts.test.tsx.snap | 0 .../__tests__/monitor_charts.test.tsx | 0 .../uptime/public/components/monitor/index.ts | 12 ++ .../__snapshots__/location_map.test.tsx.snap | 0 .../location_missing.test.tsx.snap | 0 .../location_status_tags.test.tsx.snap | 0 .../__tests__/location_map.test.tsx | 0 .../__tests__/location_missing.test.tsx | 0 .../__tests__/location_status_tags.test.tsx | 3 +- .../embeddables/__tests__/__mocks__/mock.ts | 0 .../embeddables/__tests__/map_config.test.ts | 0 .../location_map/embeddables/embedded_map.tsx | 0 .../embeddables/low_poly_layer.json | 0 .../location_map/embeddables/map_config.ts | 2 +- .../location_map/embeddables/translations.ts | 0 .../location_map/index.tsx | 0 .../location_map/location_map.tsx | 0 .../location_map/location_missing.tsx | 2 +- .../location_map/location_status_tags.tsx | 0 .../confirm_delete.test.tsx.snap | 0 .../__snapshots__/license_info.test.tsx.snap | 0 .../__snapshots__/ml_flyout.test.tsx.snap | 0 .../ml_integerations.test.tsx.snap | 0 .../__snapshots__/ml_job_link.test.tsx.snap | 0 .../__snapshots__/ml_manage_job.test.tsx.snap | 0 .../ml/__tests__/confirm_delete.test.tsx | 0 .../ml/__tests__/license_info.test.tsx | 0 .../ml/__tests__/ml_flyout.test.tsx | 0 .../ml/__tests__/ml_integerations.test.tsx | 0 .../ml/__tests__/ml_job_link.test.tsx | 0 .../ml/__tests__/ml_manage_job.test.tsx | 0 .../ml/confirm_delete.tsx | 0 .../components/monitor/ml}/index.ts | 2 +- .../ml/license_info.tsx | 0 .../ml/manage_ml_job.tsx | 2 +- .../ml/ml_flyout.tsx | 0 .../ml/ml_flyout_container.tsx | 2 +- .../ml/ml_integeration.tsx | 2 +- .../ml/ml_job_link.tsx | 0 .../ml/translations.tsx | 7 - .../monitor_charts.tsx | 7 +- .../monitor/monitor_duration/index.ts | 8 + .../monitor_duration/monitor_duration.tsx | 66 ++++++++ .../monitor_duration_container.tsx} | 11 +- .../monitor_ssl_certificate.test.tsx.snap | 0 .../monitor_status.bar.test.tsx.snap | 0 .../status_by_location.test.tsx.snap | 0 .../__test__/monitor_ssl_certificate.test.tsx | 0 .../__test__/monitor_status.bar.test.tsx | 0 .../__test__/status_by_location.test.tsx | 2 +- .../monitor_status_details/index.ts | 5 +- .../monitor_status_bar/index.ts | 9 + .../monitor_status_bar/ssl_certificate.tsx} | 0 .../monitor_status_bar/status_bar.tsx} | 4 +- .../status_bar_container.tsx | 40 +++++ .../monitor_status_bar/status_by_location.tsx | 0 .../monitor_status_bar/translations.ts | 1 + .../status_details.tsx} | 2 +- .../status_details_container.tsx | 34 ++++ .../monitor_status_details/translations.ts | 1 + .../pings => monitor/ping_histogram}/index.ts | 2 +- .../ping_histogram_container.tsx | 48 ++++++ .../__snapshots__/doc_link_body.test.tsx.snap | 0 .../__snapshots__/expanded_row.test.tsx.snap | 0 .../__snapshots__/ping_list.test.tsx.snap | 0 .../__tests__/doc_link_body.test.tsx | 0 .../ping_list/__tests__/expanded_row.test.tsx | 0 .../ping_list/__tests__/ping_list.test.tsx | 2 +- .../ping_list/doc_link_body.tsx | 0 .../ping_list/expanded_row.tsx | 0 .../ping_list/index.tsx | 1 + .../ping_list/location_name.tsx | 0 .../ping_list/ping_list.tsx | 6 +- .../ping_list/ping_list_container.tsx} | 2 +- .../parsing_error_callout.test.tsx.snap} | 0 .../__snapshots__/snapshot.test.tsx.snap | 0 .../snapshot_heading.test.tsx.snap | 0 .../__tests__/parsing_error_callout.test.tsx} | 6 +- .../__tests__/snapshot.test.tsx | 2 +- .../__tests__/snapshot_heading.test.tsx | 2 +- .../__tests__/alert_monitor_status.test.tsx | 4 +- .../alerts/alert_monitor_status.tsx | 2 +- .../alert_monitor_status.tsx | 4 +- .../alerts/alerts_containers}/index.ts | 0 .../toggle_alert_flyout_button.tsx | 4 +- .../uptime_alerts_flyout_wrapper.tsx | 6 +- .../{functional => overview}/alerts/index.ts | 1 + .../alerts/toggle_alert_flyout_button.tsx | 0 .../alerts/uptime_alerts_context_provider.tsx | 0 .../alerts/uptime_alerts_flyout_wrapper.tsx | 0 .../data_or_index_missing.test.tsx.snap | 0 .../__snapshots__/empty_state.test.tsx.snap | 0 .../__tests__/data_or_index_missing.test.tsx | 0 .../__tests__/empty_state.test.tsx | 0 .../empty_state/data_or_index_missing.tsx | 0 .../empty_state/empty_state.tsx | 0 .../empty_state/empty_state_container.tsx} | 2 +- .../empty_state/empty_state_error.tsx | 0 .../empty_state/empty_state_loading.tsx | 0 .../components/overview/empty_state/index.ts | 8 + .../filter_popover.test.tsx.snap | 0 .../filter_status_button.test.tsx.snap | 0 .../parse_filter_map.test.ts.snap | 0 .../__tests__/filter_popover.test.tsx | 0 .../__tests__/filter_status_button.test.tsx | 2 +- .../__tests__/parse_filter_map.test.ts | 0 .../__tests__/toggle_selected_item.test.ts | 0 .../filter_group/filter_group.tsx | 0 .../filter_group/filter_group_container.tsx | 4 +- .../filter_group/filter_popover.tsx | 0 .../filter_group/filter_status_button.tsx | 0 .../filter_group/index.ts | 1 + .../filter_group/parse_filter_map.ts | 0 .../filter_group/toggle_selected_item.ts | 0 .../filter_group/uptime_filter_button.tsx | 0 .../public/components/overview/index.ts | 14 ++ .../components/overview/kuery_bar/index.ts | 8 + .../kuery_bar/kuery_bar.tsx | 0 .../kuery_bar}/kuery_bar_container.tsx | 2 +- .../kuery_bar/typeahead/click_outside.js | 0 .../kuery_bar/typeahead/index.d.ts | 2 +- .../kuery_bar/typeahead/index.js | 0 .../kuery_bar/typeahead/suggestion.js | 0 .../kuery_bar/typeahead/suggestions.js | 0 .../__snapshots__/monitor_list.test.tsx.snap | 0 .../monitor_list_status_column.test.tsx.snap | 0 .../monitor_page_link.test.tsx.snap | 0 .../__tests__/monitor_list.test.tsx | 0 .../monitor_list_page_size_select.test.tsx | 0 .../monitor_list_status_column.test.tsx | 0 .../__tests__/monitor_page_link.test.tsx | 0 .../__tests__/parse_timestamp.test.ts | 0 .../monitor_list/index.ts | 2 + .../monitor_list/monitor_list.tsx | 6 +- .../monitor_list/monitor_list_container.tsx} | 5 +- .../integration_group.test.tsx.snap | 0 .../integration_link.test.tsx.snap | 0 .../monitor_list_drawer.test.tsx.snap | 0 .../monitor_status_list.test.tsx.snap | 0 .../monitor_status_row.test.tsx.snap | 0 .../most_recent_error.test.tsx.snap | 0 .../monitor_list_drawer/__tests__/data.json | 0 .../__tests__/integration_group.test.tsx | 2 +- .../__tests__/integration_link.test.tsx | 2 +- .../__tests__/monitor_list_drawer.test.tsx | 0 .../__tests__/monitor_status_list.test.tsx | 0 .../__tests__/monitor_status_row.test.tsx | 0 .../__tests__/most_recent_error.test.tsx | 0 .../actions_popover/actions_popover.tsx} | 10 +- .../actions_popover_container.tsx} | 13 +- .../actions_popover}/integration_group.tsx | 6 +- .../actions_popover}/integration_link.tsx | 0 .../monitor_list/monitor_list_drawer/index.ts | 4 +- .../list_drawer_container.tsx | 14 +- .../monitor_list_drawer.tsx | 4 +- .../monitor_status_list.tsx | 2 +- .../monitor_status_row.tsx | 0 .../monitor_list_drawer/most_recent_error.tsx | 0 .../monitor_list_page_size_select.tsx | 0 .../monitor_list_status_column.tsx | 0 .../monitor_list/monitor_page_link.tsx | 0 .../monitor_list/overview_page_link.tsx | 0 .../monitor_list/parse_timestamp.ts | 0 .../monitor_list/translations.ts | 0 .../monitor_list/types.ts | 7 - .../pages => overview}/overview_container.tsx | 8 +- .../parsing_error_callout.tsx} | 6 +- .../components/overview/snapshot/index.ts} | 6 +- .../snapshot}/snapshot.tsx | 6 +- .../overview/snapshot/snapshot_container.tsx | 34 ++++ .../snapshot}/snapshot_heading.tsx | 0 .../{functional => overview}/status_panel.tsx | 3 +- .../contexts/uptime_settings_context.tsx | 2 +- .../hooks/__tests__/use_breadcrumbs.test.tsx | 2 +- .../uptime/public/lib/alert_types/index.ts | 2 +- .../public/lib/alert_types/monitor_status.tsx | 2 +- .../lib/helper/charts/get_chart_date_label.ts | 2 +- .../lib/helper/charts/get_label_format.ts | 2 +- .../public/lib/helper/convert_measurements.ts | 2 +- .../__tests__/parse_absolute_date.test.ts | 2 +- .../parse_autorefresh_interval.test.ts | 24 --- .../legacy/plugins/uptime/public/lib/lib.ts | 3 - .../plugins/uptime/public/pages/monitor.tsx | 5 +- .../plugins/uptime/public/pages/overview.tsx | 7 +- .../uptime/public/pages/page_header.tsx | 4 +- .../legacy/plugins/uptime/public/routes.tsx | 2 +- .../uptime/public/state/api/monitor.ts | 2 +- .../public/state/api/monitor_duration.ts | 2 +- .../public/state/api/overview_filters.ts | 4 +- .../plugins/uptime/public/state/api/ping.ts | 2 +- .../uptime/public/state/api/snapshot.ts | 2 +- .../public/state/reducers/monitor_status.ts | 4 +- .../uptime/public/state/reducers/ui.ts | 2 +- .../uptime/public/state/selectors/index.ts | 10 ++ .../plugins/uptime/public/uptime_app.tsx | 8 +- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 253 files changed, 560 insertions(+), 719 deletions(-) create mode 100644 x-pack/legacy/plugins/uptime/common/graphql/types.ts rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_list/monitor_list_drawer => common}/__tests__/__snapshots__/location_link.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_list/monitor_list_drawer => common}/__tests__/location_link.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/__tests__/uptime_date_picker.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/__snapshots__/chart_empty_state.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/__snapshots__/donut_chart.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/__snapshots__/donut_chart_legend.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/__snapshots__/donut_chart_legend_row.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap (99%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/__snapshots__/monitor_bar_series.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/__snapshots__/ping_histogram.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/chart_empty_state.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/chart_wrapper.test.tsx (97%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/donut_chart.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/donut_chart_legend.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/donut_chart_legend_row.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/duration_charts.test.tsx (98%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/get_tick_format.test.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/monitor_bar_series.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/__tests__/ping_histogram.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/annotation_tooltip.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/chart_empty_state.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/chart_wrapper/chart_wrapper.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/chart_wrapper/index.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/donut_chart.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/donut_chart_legend.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/donut_chart_legend_row.tsx (100%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/common/charts/duration_chart.tsx rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/duration_line_bar_list.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/duration_line_series_list.tsx (97%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/get_tick_format.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/index.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/monitor_bar_series.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/charts/ping_histogram.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{ => common}/higher_order/__tests__/__snapshots__/responsive_wrapper.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{ => common}/higher_order/__tests__/responsive_wrapper.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{ => common}/higher_order/index.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{ => common}/higher_order/responsive_wrapper.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_list/monitor_list_drawer => common}/location_link.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => common}/uptime_date_picker.tsx (100%) delete mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/charts/snapshot_container.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/index.ts delete mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_details_container.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_chart.tsx delete mode 100644 x-pack/legacy/plugins/uptime/public/components/functional/index.ts delete mode 100644 x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/index.ts delete mode 100644 x-pack/legacy/plugins/uptime/public/components/functional/search_schema.ts rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/__tests__/__snapshots__/monitor_charts.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/__tests__/monitor_charts.test.tsx (100%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/monitor/index.ts rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/__tests__/__snapshots__/location_map.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/__tests__/location_map.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/__tests__/location_missing.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/__tests__/location_status_tags.test.tsx (97%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/embeddables/__tests__/__mocks__/mock.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/embeddables/__tests__/map_config.test.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/embeddables/embedded_map.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/embeddables/low_poly_layer.json (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/embeddables/map_config.ts (98%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/embeddables/translations.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/index.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/location_map.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/location_missing.tsx (97%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/location_map/location_status_tags.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/__snapshots__/license_info.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/confirm_delete.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/license_info.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/ml_flyout.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/ml_integerations.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/ml_job_link.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/__tests__/ml_manage_job.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/confirm_delete.tsx (100%) rename x-pack/legacy/plugins/uptime/{common/domain_types => public/components/monitor/ml}/index.ts (81%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/license_info.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/manage_ml_job.tsx (97%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/ml_flyout.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/ml_flyout_container.tsx (98%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/ml_integeration.tsx (98%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/ml_job_link.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{monitor_details => monitor}/ml/translations.tsx (95%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_charts.tsx (68%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/index.ts create mode 100644 x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration.tsx rename x-pack/legacy/plugins/uptime/public/components/{connected/charts/monitor_duration.tsx => monitor/monitor_duration/monitor_duration_container.tsx} (91%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/__test__/__snapshots__/monitor_ssl_certificate.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/__test__/__snapshots__/monitor_status.bar.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/__test__/__snapshots__/status_by_location.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/__test__/monitor_ssl_certificate.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/__test__/monitor_status.bar.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/__test__/status_by_location.test.tsx (98%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/index.ts (64%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/index.ts rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx => monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx} (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx => monitor/monitor_status_details/monitor_status_bar/status_bar.tsx} (95%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar_container.tsx rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/monitor_status_bar/status_by_location.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/monitor_status_bar/translations.ts (99%) rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_status_details/monitor_status_details.tsx => monitor/monitor_status_details/status_details.tsx} (97%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details_container.tsx rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/monitor_status_details/translations.ts (99%) rename x-pack/legacy/plugins/uptime/public/components/{connected/pings => monitor/ping_histogram}/index.ts (80%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/__tests__/doc_link_body.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/__tests__/expanded_row.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/__tests__/ping_list.test.tsx (99%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/doc_link_body.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/expanded_row.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/index.tsx (85%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/location_name.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => monitor}/ping_list/ping_list.tsx (98%) rename x-pack/legacy/plugins/uptime/public/components/{connected/pings/ping_list.tsx => monitor/ping_list/ping_list_container.tsx} (96%) rename x-pack/legacy/plugins/uptime/public/components/{functional/__tests__/__snapshots__/overview_page_parsing_error_callout.test.tsx.snap => overview/__tests__/__snapshots__/parsing_error_callout.test.tsx.snap} (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/__tests__/__snapshots__/snapshot.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/__tests__/__snapshots__/snapshot_heading.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional/__tests__/overview_page_parsing_error_callout.test.tsx => overview/__tests__/parsing_error_callout.test.tsx} (76%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/__tests__/snapshot.test.tsx (92%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/__tests__/snapshot_heading.test.tsx (93%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/alerts/__tests__/alert_monitor_status.test.tsx (98%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/alerts/alert_monitor_status.tsx (99%) rename x-pack/legacy/plugins/uptime/public/components/{connected/alerts => overview/alerts/alerts_containers}/alert_monitor_status.tsx (86%) rename x-pack/legacy/plugins/uptime/public/components/{connected/alerts => overview/alerts/alerts_containers}/index.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{connected/alerts => overview/alerts/alerts_containers}/toggle_alert_flyout_button.tsx (80%) rename x-pack/legacy/plugins/uptime/public/components/{connected/alerts => overview/alerts/alerts_containers}/uptime_alerts_flyout_wrapper.tsx (83%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/alerts/index.ts (93%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/alerts/toggle_alert_flyout_button.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/alerts/uptime_alerts_context_provider.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/alerts/uptime_alerts_flyout_wrapper.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/empty_state/__tests__/data_or_index_missing.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/empty_state/__tests__/empty_state.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/empty_state/data_or_index_missing.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/empty_state/empty_state.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{connected/empty_state/empty_state.tsx => overview/empty_state/empty_state_container.tsx} (95%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/empty_state/empty_state_error.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/empty_state/empty_state_loading.tsx (100%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/overview/empty_state/index.ts rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/__tests__/__snapshots__/filter_status_button.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/__tests__/__snapshots__/parse_filter_map.test.ts.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/__tests__/filter_popover.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/__tests__/filter_status_button.test.tsx (93%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/__tests__/parse_filter_map.test.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/__tests__/toggle_selected_item.test.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/filter_group.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{connected => overview}/filter_group/filter_group_container.tsx (94%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/filter_popover.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/filter_status_button.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/index.ts (84%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/parse_filter_map.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/toggle_selected_item.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/filter_group/uptime_filter_button.tsx (100%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/overview/index.ts create mode 100644 x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/index.ts rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/kuery_bar/kuery_bar.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{connected/kuerybar => overview/kuery_bar}/kuery_bar_container.tsx (90%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/kuery_bar/typeahead/click_outside.js (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/kuery_bar/typeahead/index.d.ts (95%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/kuery_bar/typeahead/index.js (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/kuery_bar/typeahead/suggestion.js (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/kuery_bar/typeahead/suggestions.js (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/__tests__/__snapshots__/monitor_list_status_column.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/__tests__/__snapshots__/monitor_page_link.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/__tests__/monitor_list.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/__tests__/monitor_list_page_size_select.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/__tests__/monitor_list_status_column.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/__tests__/monitor_page_link.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/__tests__/parse_timestamp.test.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/index.ts (69%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list.tsx (97%) rename x-pack/legacy/plugins/uptime/public/components/{connected/monitor/monitor_list.tsx => overview/monitor_list/monitor_list_container.tsx} (93%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_group.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_link.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_list.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_row.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/data.json (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx (94%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/integration_link.test.tsx (93%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/monitor_status_row.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/__tests__/most_recent_error.test.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_list/monitor_list_drawer/monitor_list_actions_popover.tsx => overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover.tsx} (89%) rename x-pack/legacy/plugins/uptime/public/components/{connected/monitor/drawer_popover_container.tsx => overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover_container.tsx} (63%) rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_list/monitor_list_drawer => overview/monitor_list/monitor_list_drawer/actions_popover}/integration_group.tsx (98%) rename x-pack/legacy/plugins/uptime/public/components/{functional/monitor_list/monitor_list_drawer => overview/monitor_list/monitor_list_drawer/actions_popover}/integration_link.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/index.ts (63%) rename x-pack/legacy/plugins/uptime/public/components/{connected/monitor => overview/monitor_list/monitor_list_drawer}/list_drawer_container.tsx (72%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx (93%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/monitor_status_list.tsx (97%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/monitor_status_row.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_drawer/most_recent_error.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_page_size_select.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_list_status_column.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/monitor_page_link.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/overview_page_link.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/parse_timestamp.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/translations.ts (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/monitor_list/types.ts (83%) rename x-pack/legacy/plugins/uptime/public/components/{connected/pages => overview}/overview_container.tsx (74%) rename x-pack/legacy/plugins/uptime/public/components/{functional/overview_page_parsing_error_callout.tsx => overview/parsing_error_callout.tsx} (89%) rename x-pack/legacy/plugins/uptime/{common/domain_types/monitors.ts => public/components/overview/snapshot/index.ts} (71%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview/snapshot}/snapshot.tsx (85%) create mode 100644 x-pack/legacy/plugins/uptime/public/components/overview/snapshot/snapshot_container.tsx rename x-pack/legacy/plugins/uptime/public/components/{functional => overview/snapshot}/snapshot_heading.tsx (100%) rename x-pack/legacy/plugins/uptime/public/components/{functional => overview}/status_panel.tsx (87%) delete mode 100644 x-pack/legacy/plugins/uptime/public/lib/helper/url_params/__tests__/parse_autorefresh_interval.test.ts diff --git a/x-pack/legacy/plugins/uptime/common/constants/chart_format_limits.ts b/x-pack/legacy/plugins/uptime/common/constants/chart_format_limits.ts index f291450ab2a7a..3bd204a003c9d 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/chart_format_limits.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/chart_format_limits.ts @@ -11,7 +11,7 @@ const WEEK = DAY * 7; const MONTH = WEEK * 4; /** - * These contsants are used by the charting code to determine + * These constants are used by the charting code to determine * what label should be applied to chart axes so as to help users * understand the timeseries data they're being shown. */ diff --git a/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts b/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts index c6b79afd9043b..0c493326add72 100644 --- a/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts +++ b/x-pack/legacy/plugins/uptime/common/constants/context_defaults.ts @@ -11,7 +11,7 @@ import { CursorDirection, SortOrder } from '../runtime_types'; */ export const CONTEXT_DEFAULTS = { /** - * The application cannot assume a basepath. + * The application cannot assume a basePath. */ BASE_PATH: '', diff --git a/x-pack/legacy/plugins/uptime/common/graphql/types.ts b/x-pack/legacy/plugins/uptime/common/graphql/types.ts new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts b/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts index 9018f4acaa320..e07c46fa01cfe 100644 --- a/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts +++ b/x-pack/legacy/plugins/uptime/common/runtime_types/common.ts @@ -33,7 +33,6 @@ export const DateRangeType = t.type({ }); export type Summary = t.TypeOf; -export type CheckGeo = t.TypeOf; export type Location = t.TypeOf; export type StatesIndexStatus = t.TypeOf; export type DateRange = t.TypeOf; diff --git a/x-pack/legacy/plugins/uptime/common/types/index.ts b/x-pack/legacy/plugins/uptime/common/types/index.ts index fcbb92caf26d5..a32eabd49a3e5 100644 --- a/x-pack/legacy/plugins/uptime/common/types/index.ts +++ b/x-pack/legacy/plugins/uptime/common/types/index.ts @@ -35,3 +35,7 @@ export interface MonitorDurationResult { /** The average values for the monitor duration. */ locationDurationLines: LocationDurationLine[]; } + +export interface MonitorIdParam { + monitorId: string; +} diff --git a/x-pack/legacy/plugins/uptime/public/apps/plugin.ts b/x-pack/legacy/plugins/uptime/public/apps/plugin.ts index eec49418910f8..e73598c44c9f0 100644 --- a/x-pack/legacy/plugins/uptime/public/apps/plugin.ts +++ b/x-pack/legacy/plugins/uptime/public/apps/plugin.ts @@ -4,23 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - LegacyCoreStart, - LegacyCoreSetup, - PluginInitializerContext, - AppMountParameters, -} from 'src/core/public'; -import { PluginsStart, PluginsSetup } from 'ui/new_platform/new_platform'; +import { LegacyCoreSetup, PluginInitializerContext, AppMountParameters } from 'src/core/public'; +import { PluginsSetup } from 'ui/new_platform/new_platform'; import { FeatureCatalogueCategory } from '../../../../../../src/plugins/home/public'; import { UMFrontendLibs } from '../lib/lib'; import { PLUGIN } from '../../common/constants'; import { getKibanaFrameworkAdapter } from '../lib/adapters/framework/new_platform_adapter'; -export interface StartObject { - core: LegacyCoreStart; - plugins: PluginsStart; -} - export interface SetupObject { core: LegacyCoreSetup; plugins: PluginsSetup; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/location_link.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/__tests__/__snapshots__/location_link.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/location_link.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/__tests__/__snapshots__/location_link.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/__tests__/__snapshots__/uptime_date_picker.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/location_link.test.tsx b/x-pack/legacy/plugins/uptime/public/components/common/__tests__/location_link.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/location_link.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/__tests__/location_link.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/uptime_date_picker.test.tsx b/x-pack/legacy/plugins/uptime/public/components/common/__tests__/uptime_date_picker.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/uptime_date_picker.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/__tests__/uptime_date_picker.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/chart_empty_state.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/chart_empty_state.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/chart_empty_state.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/chart_empty_state.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/chart_wrapper.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/donut_chart.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/donut_chart.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/donut_chart.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/donut_chart.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/donut_chart_legend.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/donut_chart_legend.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/donut_chart_legend.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/donut_chart_legend.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/donut_chart_legend_row.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/donut_chart_legend_row.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/donut_chart_legend_row.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/donut_chart_legend_row.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap similarity index 99% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap index 6c38f3e338cfd..96918ab68f716 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap +++ b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/__snapshots__/duration_charts.test.tsx.snap @@ -53,7 +53,6 @@ exports[`MonitorCharts component renders the component without errors 1`] = ` > { const component = shallowWithRouter( diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/get_tick_format.test.ts b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/get_tick_format.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/get_tick_format.test.ts rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/get_tick_format.test.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/monitor_bar_series.test.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/monitor_bar_series.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/monitor_bar_series.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/monitor_bar_series.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/ping_histogram.test.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/ping_histogram.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/__tests__/ping_histogram.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/__tests__/ping_histogram.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/annotation_tooltip.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/annotation_tooltip.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/annotation_tooltip.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/annotation_tooltip.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_empty_state.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/chart_empty_state.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_empty_state.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/chart_empty_state.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_wrapper/chart_wrapper.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/chart_wrapper/chart_wrapper.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_wrapper/chart_wrapper.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/chart_wrapper/chart_wrapper.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_wrapper/index.ts b/x-pack/legacy/plugins/uptime/public/components/common/charts/chart_wrapper/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/chart_wrapper/index.ts rename to x-pack/legacy/plugins/uptime/public/components/common/charts/chart_wrapper/index.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/donut_chart.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/donut_chart.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart_legend.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/donut_chart_legend.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart_legend.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/donut_chart_legend.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart_legend_row.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/donut_chart_legend_row.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/donut_chart_legend_row.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/donut_chart_legend_row.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/common/charts/duration_chart.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/duration_chart.tsx new file mode 100644 index 0000000000000..c82b2a1cf9fe2 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/common/charts/duration_chart.tsx @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import moment from 'moment'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { Axis, Chart, Position, timeFormatter, Settings, SeriesIdentifier } from '@elastic/charts'; +import { getChartDateLabel } from '../../../lib/helper'; +import { LocationDurationLine } from '../../../../common/types'; +import { DurationLineSeriesList } from './duration_line_series_list'; +import { ChartWrapper } from './chart_wrapper'; +import { useUrlParams } from '../../../hooks'; +import { getTickFormat } from './get_tick_format'; +import { ChartEmptyState } from './chart_empty_state'; +import { DurationAnomaliesBar } from './duration_line_bar_list'; +import { AnomalyRecords } from '../../../state/actions'; + +interface DurationChartProps { + /** + * Timeseries data that is used to express an average line series + * on the duration chart. One entry per location + */ + locationDurationLines: LocationDurationLine[]; + + /** + * To represent the loading spinner on chart + */ + loading: boolean; + + anomalies: AnomalyRecords | null; +} + +/** + * This chart is intended to visualize monitor duration performance over time to + * the users in a helpful way. Its x-axis is based on a timeseries, the y-axis is in + * milliseconds. + * @param props The props required for this component to render properly + */ +export const DurationChartComponent = ({ + locationDurationLines, + anomalies, + loading, +}: DurationChartProps) => { + const hasLines = locationDurationLines.length > 0; + const [getUrlParams, updateUrlParams] = useUrlParams(); + const { absoluteDateRangeStart: min, absoluteDateRangeEnd: max } = getUrlParams(); + + const [hiddenLegends, setHiddenLegends] = useState([]); + + const onBrushEnd = (minX: number, maxX: number) => { + updateUrlParams({ + dateRangeStart: moment(minX).toISOString(), + dateRangeEnd: moment(maxX).toISOString(), + }); + }; + + const legendToggleVisibility = (legendItem: SeriesIdentifier | null) => { + if (legendItem) { + setHiddenLegends(prevState => { + if (prevState.includes(legendItem.specId)) { + return [...prevState.filter(item => item !== legendItem.specId)]; + } else { + return [...prevState, legendItem.specId]; + } + }); + } + }; + + return ( + + {hasLines ? ( + + + + getTickFormat(d)} + title={i18n.translate('xpack.uptime.monitorCharts.durationChart.leftAxis.title', { + defaultMessage: 'Duration ms', + })} + /> + + + + ) : ( + up }} + /> + } + title={i18n.translate('xpack.uptime.durationChart.emptyPrompt.title', { + defaultMessage: 'No duration data available', + })} + /> + )} + + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_line_bar_list.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/duration_line_bar_list.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_line_bar_list.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/duration_line_bar_list.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_line_series_list.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/duration_line_series_list.tsx similarity index 97% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_line_series_list.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/duration_line_series_list.tsx index 912bc5bb0501b..4223e918393b6 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_line_series_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/common/charts/duration_line_series_list.tsx @@ -21,7 +21,7 @@ export const DurationLineSeriesList = ({ lines }: Props) => ( // this id is used for the line chart representing the average duration length data={line.map(({ x, y }) => [x, microsToMillis(y || null)])} id={`loc-avg-${name}`} - key={`locline-${name}`} + key={`loc-line-${name}`} name={name} xAccessor={0} xScaleType="time" diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/get_tick_format.ts b/x-pack/legacy/plugins/uptime/public/components/common/charts/get_tick_format.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/get_tick_format.ts rename to x-pack/legacy/plugins/uptime/public/components/common/charts/get_tick_format.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/index.ts b/x-pack/legacy/plugins/uptime/public/components/common/charts/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/index.ts rename to x-pack/legacy/plugins/uptime/public/components/common/charts/index.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/monitor_bar_series.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/monitor_bar_series.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/monitor_bar_series.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/monitor_bar_series.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/common/charts/ping_histogram.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/charts/ping_histogram.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/charts/ping_histogram.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/higher_order/__tests__/__snapshots__/responsive_wrapper.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/common/higher_order/__tests__/__snapshots__/responsive_wrapper.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/higher_order/__tests__/__snapshots__/responsive_wrapper.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/common/higher_order/__tests__/__snapshots__/responsive_wrapper.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/higher_order/__tests__/responsive_wrapper.test.tsx b/x-pack/legacy/plugins/uptime/public/components/common/higher_order/__tests__/responsive_wrapper.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/higher_order/__tests__/responsive_wrapper.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/higher_order/__tests__/responsive_wrapper.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/higher_order/index.ts b/x-pack/legacy/plugins/uptime/public/components/common/higher_order/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/higher_order/index.ts rename to x-pack/legacy/plugins/uptime/public/components/common/higher_order/index.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/higher_order/responsive_wrapper.tsx b/x-pack/legacy/plugins/uptime/public/components/common/higher_order/responsive_wrapper.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/higher_order/responsive_wrapper.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/higher_order/responsive_wrapper.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/location_link.tsx b/x-pack/legacy/plugins/uptime/public/components/common/location_link.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/location_link.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/location_link.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/uptime_date_picker.tsx b/x-pack/legacy/plugins/uptime/public/components/common/uptime_date_picker.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/uptime_date_picker.tsx rename to x-pack/legacy/plugins/uptime/public/components/common/uptime_date_picker.tsx index 7d2123af8ff9c..4254004dba4e0 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/uptime_date_picker.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/common/uptime_date_picker.tsx @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiSuperDatePicker } from '@elastic/eui'; import React, { useContext } from 'react'; +import { EuiSuperDatePicker } from '@elastic/eui'; import { useUrlParams } from '../../hooks'; import { CLIENT_DEFAULTS } from '../../../common/constants'; import { UptimeRefreshContext, UptimeSettingsContext } from '../../contexts'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx deleted file mode 100644 index cf35dbf4e5206..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/ping_histogram.tsx +++ /dev/null @@ -1,82 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useEffect } from 'react'; -import { connect } from 'react-redux'; -import { AppState } from '../../../state'; -import { - PingHistogramComponent, - PingHistogramComponentProps, -} from '../../functional/charts/ping_histogram'; -import { getPingHistogram } from '../../../state/actions'; -import { selectPingHistogram } from '../../../state/selectors'; -import { withResponsiveWrapper, ResponsiveWrapperProps } from '../../higher_order'; -import { GetPingHistogramParams, HistogramResult } from '../../../../common/runtime_types'; -import { useGetUrlParams } from '../../../hooks'; - -type Props = ResponsiveWrapperProps & - Pick & - DispatchProps & { lastRefresh: number; monitorId?: string; esKuery?: string }; - -const PingHistogramContainer: React.FC = ({ - data, - loadData, - monitorId, - lastRefresh, - height, - loading, - esKuery, -}) => { - const { - absoluteDateRangeStart, - absoluteDateRangeEnd, - dateRangeStart: dateStart, - dateRangeEnd: dateEnd, - statusFilter, - } = useGetUrlParams(); - - useEffect(() => { - loadData({ monitorId, dateStart, dateEnd, statusFilter, filters: esKuery }); - }, [loadData, dateStart, dateEnd, monitorId, statusFilter, lastRefresh, esKuery]); - return ( - - ); -}; - -interface StateProps { - data: HistogramResult | null; - loading: boolean; - lastRefresh: number; - esKuery: string; -} - -interface DispatchProps { - loadData: typeof getPingHistogram; -} - -const mapStateToProps = (state: AppState): StateProps => ({ ...selectPingHistogram(state) }); - -const mapDispatchToProps = (dispatch: any): DispatchProps => ({ - loadData: (params: GetPingHistogramParams) => { - return dispatch(getPingHistogram(params)); - }, -}); - -export const PingHistogram = connect< - StateProps, - DispatchProps, - Pick, - AppState ->( - mapStateToProps, - mapDispatchToProps -)(withResponsiveWrapper(PingHistogramContainer)); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/snapshot_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/charts/snapshot_container.tsx deleted file mode 100644 index 39ead242527f8..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/snapshot_container.tsx +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useEffect } from 'react'; -import { connect } from 'react-redux'; -import { useGetUrlParams } from '../../../hooks'; -import { AppState } from '../../../state'; -import { getSnapshotCountAction } from '../../../state/actions'; -import { SnapshotComponent } from '../../functional/snapshot'; -import { Snapshot as SnapshotType } from '../../../../common/runtime_types'; -import { SnapShotQueryParams } from '../../../state/api'; - -/** - * Props expected from parent components. - */ -interface OwnProps { - /** - * Height is needed, since by default charts takes height of 100% - */ - height?: string; -} - -/** - * Props given by the Redux store based on action input. - */ -interface StoreProps { - count: SnapshotType; - lastRefresh: number; - loading: boolean; - esKuery: string; -} - -/** - * Contains functions that will dispatch actions used - * for this component's life cycle - */ -interface DispatchProps { - loadSnapshotCount: typeof getSnapshotCountAction; -} - -/** - * Props used to render the Snapshot component. - */ -type Props = OwnProps & StoreProps & DispatchProps; - -export const Container: React.FC = ({ - count, - height, - lastRefresh, - loading, - esKuery, - loadSnapshotCount, -}: Props) => { - const { dateRangeStart, dateRangeEnd, statusFilter } = useGetUrlParams(); - - useEffect(() => { - loadSnapshotCount({ dateRangeStart, dateRangeEnd, filters: esKuery, statusFilter }); - }, [dateRangeStart, dateRangeEnd, esKuery, lastRefresh, loadSnapshotCount, statusFilter]); - return ; -}; - -/** - * Provides state to connected component. - * @param state the root app state - */ -const mapStateToProps = ({ - snapshot: { count, loading }, - ui: { lastRefresh, esKuery }, -}: AppState): StoreProps => ({ - count, - lastRefresh, - loading, - esKuery, -}); - -/** - * Used for fetching snapshot counts. - * @param dispatch redux-provided action dispatcher - */ -const mapDispatchToProps = (dispatch: any) => ({ - loadSnapshotCount: (params: SnapShotQueryParams): DispatchProps => { - return dispatch(getSnapshotCountAction(params)); - }, -}); - -export const Snapshot = connect( - // @ts-ignore connect is expecting null | undefined for some reason - mapStateToProps, - mapDispatchToProps -)(Container); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts b/x-pack/legacy/plugins/uptime/public/components/connected/index.ts deleted file mode 100644 index 94e2529a46a00..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/connected/index.ts +++ /dev/null @@ -1,19 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { AlertMonitorStatus, ToggleAlertFlyoutButton, UptimeAlertsFlyoutWrapper } from './alerts'; -export { PingHistogram } from './charts/ping_histogram'; -export { Snapshot } from './charts/snapshot_container'; -export { KueryBar } from './kuerybar/kuery_bar_container'; -export { FilterGroup } from './filter_group/filter_group_container'; -export { MonitorStatusDetails } from './monitor/status_details_container'; -export { MonitorStatusBar } from './monitor/status_bar_container'; -export { MonitorList } from './monitor/monitor_list'; -export { MonitorListDrawer } from './monitor/list_drawer_container'; -export { MonitorListActionsPopover } from './monitor/drawer_popover_container'; -export { PingList, PingListProps } from './pings'; -export { DurationChart } from './charts/monitor_duration'; -export { EmptyState } from './empty_state/empty_state'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx deleted file mode 100644 index 3a96aa7c0275b..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_bar_container.tsx +++ /dev/null @@ -1,71 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useContext, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; -import { AppState } from '../../../state'; -import { monitorLocationsSelector, monitorStatusSelector } from '../../../state/selectors'; -import { MonitorStatusBarComponent } from '../../functional/monitor_status_details/monitor_status_bar'; -import { getMonitorStatusAction } from '../../../state/actions'; -import { useGetUrlParams } from '../../../hooks'; -import { Ping } from '../../../../common/runtime_types'; -import { MonitorLocations } from '../../../../common/runtime_types/monitor'; -import { UptimeRefreshContext } from '../../../contexts'; - -interface StateProps { - monitorStatus: Ping; - monitorLocations: MonitorLocations; -} - -interface DispatchProps { - loadMonitorStatus: typeof getMonitorStatusAction; -} - -interface OwnProps { - monitorId: string; -} - -type Props = OwnProps & StateProps & DispatchProps; - -const Container: React.FC = ({ - loadMonitorStatus, - monitorId, - monitorStatus, - monitorLocations, -}: Props) => { - const { lastRefresh } = useContext(UptimeRefreshContext); - - const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams(); - - useEffect(() => { - loadMonitorStatus({ dateStart, dateEnd, monitorId }); - }, [monitorId, dateStart, dateEnd, loadMonitorStatus, lastRefresh]); - - return ( - - ); -}; - -const mapStateToProps = (state: AppState, ownProps: OwnProps) => ({ - monitorStatus: monitorStatusSelector(state), - monitorLocations: monitorLocationsSelector(state, ownProps.monitorId), -}); - -const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({ - loadMonitorStatus: params => dispatch(getMonitorStatusAction(params)), -}); - -// @ts-ignore TODO: Investigate typescript issues here -export const MonitorStatusBar = connect( - // @ts-ignore TODO: Investigate typescript issues here - mapStateToProps, - mapDispatchToProps -)(Container); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_details_container.tsx b/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_details_container.tsx deleted file mode 100644 index 9d2e48830fbfe..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/status_details_container.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useContext, useEffect } from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; -import { useGetUrlParams } from '../../../hooks'; -import { AppState } from '../../../state'; -import { monitorLocationsSelector } from '../../../state/selectors'; -import { getMonitorLocationsAction, MonitorLocationsPayload } from '../../../state/actions/monitor'; -import { MonitorStatusDetailsComponent } from '../../functional/monitor_status_details'; -import { MonitorLocations } from '../../../../common/runtime_types'; -import { UptimeRefreshContext } from '../../../contexts'; - -interface OwnProps { - monitorId: string; -} - -interface StoreProps { - monitorLocations: MonitorLocations; -} - -interface DispatchProps { - loadMonitorLocations: typeof getMonitorLocationsAction; -} - -type Props = OwnProps & StoreProps & DispatchProps; - -export const Container: React.FC = ({ - loadMonitorLocations, - monitorLocations, - monitorId, -}: Props) => { - const { lastRefresh } = useContext(UptimeRefreshContext); - - const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams(); - - useEffect(() => { - loadMonitorLocations({ dateStart, dateEnd, monitorId }); - }, [loadMonitorLocations, monitorId, dateStart, dateEnd, lastRefresh]); - - return ( - - ); -}; -const mapStateToProps = (state: AppState, { monitorId }: OwnProps) => ({ - monitorLocations: monitorLocationsSelector(state, monitorId), -}); - -const mapDispatchToProps = (dispatch: Dispatch) => ({ - loadMonitorLocations: (params: MonitorLocationsPayload) => { - dispatch(getMonitorLocationsAction(params)); - }, -}); - -export const MonitorStatusDetails = connect( - // @ts-ignore TODO: Investigate typescript issues here - mapStateToProps, - mapDispatchToProps -)(Container); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_chart.tsx b/x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_chart.tsx deleted file mode 100644 index ec2081d715554..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/functional/charts/duration_chart.tsx +++ /dev/null @@ -1,155 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import React, { useState } from 'react'; -import { i18n } from '@kbn/i18n'; -import moment from 'moment'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; -import { Axis, Chart, Position, timeFormatter, Settings, SeriesIdentifier } from '@elastic/charts'; -import { getChartDateLabel } from '../../../lib/helper'; -import { LocationDurationLine } from '../../../../common/types'; -import { DurationLineSeriesList } from './duration_line_series_list'; -import { ChartWrapper } from './chart_wrapper'; -import { useUrlParams } from '../../../hooks'; -import { getTickFormat } from './get_tick_format'; -import { ChartEmptyState } from './chart_empty_state'; -import { DurationAnomaliesBar } from './duration_line_bar_list'; -import { MLIntegrationComponent } from '../../monitor_details/ml/ml_integeration'; -import { AnomalyRecords } from '../../../state/actions'; - -interface DurationChartProps { - /** - * Timeseries data that is used to express an average line series - * on the duration chart. One entry per location - */ - locationDurationLines: LocationDurationLine[]; - - /** - * To represent the loading spinner on chart - */ - loading: boolean; - - hasMLJob: boolean; - - anomalies: AnomalyRecords | null; -} - -/** - * This chart is intended to visualize monitor duration performance over time to - * the users in a helpful way. Its x-axis is based on a timeseries, the y-axis is in - * milliseconds. - * @param props The props required for this component to render properly - */ -export const DurationChartComponent = ({ - locationDurationLines, - anomalies, - loading, - hasMLJob, -}: DurationChartProps) => { - const hasLines = locationDurationLines.length > 0; - const [getUrlParams, updateUrlParams] = useUrlParams(); - const { absoluteDateRangeStart: min, absoluteDateRangeEnd: max } = getUrlParams(); - - const [hiddenLegends, setHiddenLegends] = useState([]); - - const onBrushEnd = (minX: number, maxX: number) => { - updateUrlParams({ - dateRangeStart: moment(minX).toISOString(), - dateRangeEnd: moment(maxX).toISOString(), - }); - }; - - const legendToggleVisibility = (legendItem: SeriesIdentifier | null) => { - if (legendItem) { - setHiddenLegends(prevState => { - if (prevState.includes(legendItem.specId)) { - return [...prevState.filter(item => item !== legendItem.specId)]; - } else { - return [...prevState, legendItem.specId]; - } - }); - } - }; - - return ( - <> - - - - -

- {hasMLJob ? ( - - ) : ( - - )} -

-
-
- - - -
- - - {hasLines ? ( - - - - getTickFormat(d)} - title={i18n.translate('xpack.uptime.monitorCharts.durationChart.leftAxis.title', { - defaultMessage: 'Duration ms', - })} - /> - - - - ) : ( - up }} - /> - } - title={i18n.translate('xpack.uptime.durationChart.emptyPrompt.title', { - defaultMessage: 'No duration data available', - })} - /> - )} - -
- - ); -}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/index.ts deleted file mode 100644 index 07809561c31b7..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/functional/index.ts +++ /dev/null @@ -1,20 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { - ToggleAlertFlyoutButtonComponent, - UptimeAlertsContextProvider, - UptimeAlertsFlyoutWrapperComponent, -} from './alerts'; -export * from './alerts'; -export { DonutChart } from './charts/donut_chart'; -export { KueryBarComponent } from './kuery_bar/kuery_bar'; -export { MonitorCharts } from './monitor_charts'; -export { MonitorListComponent } from './monitor_list'; -export { OverviewPageParsingErrorCallout } from './overview_page_parsing_error_callout'; -export { PingListComponent } from './ping_list'; -export { PingHistogramComponent } from './charts'; -export { StatusPanel } from './status_panel'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/index.ts b/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/index.ts deleted file mode 100644 index 0cb11587eee48..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/index.ts +++ /dev/null @@ -1,8 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export { MonitorSSLCertificate } from './monitor_ssl_certificate'; -export { MonitorStatusBarComponent } from './monitor_status_bar'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/search_schema.ts b/x-pack/legacy/plugins/uptime/public/components/functional/search_schema.ts deleted file mode 100644 index bd451a9835288..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/components/functional/search_schema.ts +++ /dev/null @@ -1,17 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -export const filterBarSearchSchema = { - strict: true, - fields: { - 'monitor.id': { type: 'string' }, - 'monitor.status': { type: 'string' }, - 'monitor.ip': { type: 'string' }, - 'monitor.host': { type: 'string' }, - 'monitor.scheme': { type: 'string' }, - 'url.port': { type: 'number' }, - }, -}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_charts.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/__tests__/__snapshots__/monitor_charts.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/monitor_charts.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/__tests__/__snapshots__/monitor_charts.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/monitor_charts.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/__tests__/monitor_charts.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/monitor_charts.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/__tests__/monitor_charts.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/index.ts new file mode 100644 index 0000000000000..cb7b27afded02 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/index.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; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './ml'; +export * from './ping_list'; +export * from './location_map'; +export * from './monitor_status_details'; +export * from './ping_histogram'; +export * from './monitor_charts'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_map.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_map.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_map.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_map.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_missing.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/__snapshots__/location_status_tags.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_map.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_map.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_map.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_map.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_missing.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_missing.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_missing.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_missing.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_status_tags.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_status_tags.test.tsx similarity index 97% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_status_tags.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_status_tags.test.tsx index 2359938dbbc35..7dde38af99fc3 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/__tests__/location_status_tags.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/__tests__/location_status_tags.test.tsx @@ -8,9 +8,8 @@ import React from 'react'; import moment from 'moment'; import { renderWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; import { MonitorLocation } from '../../../../../common/runtime_types/monitor'; -import { LocationStatusTags } from '../'; +import { LocationStatusTags } from '../index'; -// Failing: https://github.com/elastic/kibana/issues/54818 describe('LocationStatusTags component', () => { let monitorLocations: MonitorLocation[]; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__tests__/__mocks__/mock.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/__tests__/__mocks__/mock.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__tests__/__mocks__/mock.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/__tests__/__mocks__/mock.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__tests__/map_config.test.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/__tests__/map_config.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/__tests__/map_config.test.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/__tests__/map_config.test.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/embedded_map.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/embedded_map.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/embedded_map.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/low_poly_layer.json b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/low_poly_layer.json similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/low_poly_layer.json rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/low_poly_layer.json diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/map_config.ts similarity index 98% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/map_config.ts index a43edae438252..ddb52e119fa87 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/map_config.ts +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/map_config.ts @@ -5,7 +5,7 @@ */ import lowPolyLayerFeatures from './low_poly_layer.json'; -import { LocationPoint } from './embedded_map.js'; +import { LocationPoint } from './embedded_map'; import { UptimeAppColors } from '../../../../uptime_app'; /** diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/translations.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/translations.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/embeddables/translations.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/embeddables/translations.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/index.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/index.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/index.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/index.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_map.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_map.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_map.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_missing.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_missing.tsx similarity index 97% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_missing.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_missing.tsx index a20889f6cc653..6ce31e4cc8243 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_missing.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_missing.tsx @@ -16,7 +16,7 @@ import { } from '@elastic/eui'; import styled from 'styled-components'; import { FormattedMessage } from '@kbn/i18n/react'; -import { LocationLink } from '../monitor_list/monitor_list_drawer'; +import { LocationLink } from '../../common/location_link'; const EuiPopoverRight = styled(EuiFlexItem)` margin-left: auto; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_status_tags.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_status_tags.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/location_map/location_status_tags.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/location_map/location_status_tags.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/confirm_delete.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/license_info.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/license_info.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/license_info.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_flyout.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_integerations.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_job_link.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/__snapshots__/ml_manage_job.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/confirm_delete.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/confirm_delete.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/confirm_delete.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/confirm_delete.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/license_info.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/license_info.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/license_info.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/license_info.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_flyout.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_flyout.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_flyout.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_integerations.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_integerations.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_integerations.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_integerations.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_job_link.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_job_link.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_job_link.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_job_link.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_manage_job.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_manage_job.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/__tests__/ml_manage_job.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/__tests__/ml_manage_job.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/confirm_delete.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/confirm_delete.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/confirm_delete.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/confirm_delete.tsx diff --git a/x-pack/legacy/plugins/uptime/common/domain_types/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/index.ts similarity index 81% rename from x-pack/legacy/plugins/uptime/common/domain_types/index.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/index.ts index 1cf72ca2dac0b..c644c94d13878 100644 --- a/x-pack/legacy/plugins/uptime/common/domain_types/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export * from './monitors'; +export { ManageMLJobComponent } from './manage_ml_job'; diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/license_info.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/license_info.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/license_info.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/license_info.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx similarity index 97% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx index ec3e8bb2b9f68..46ac24e9455e5 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/manage_ml_job.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/manage_ml_job.tsx @@ -13,7 +13,7 @@ import { UptimeSettingsContext } from '../../../contexts'; import * as labels from './translations'; import { getMLJobLinkHref } from './ml_job_link'; import { useGetUrlParams } from '../../../hooks'; -import { useMonitorId } from '../../../hooks/use_monitor'; +import { useMonitorId } from '../../../hooks'; interface Props { hasMLJob: boolean; diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout_container.tsx similarity index 98% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout_container.tsx index a13de192cc443..c3e8579ca4837 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_flyout_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_flyout_container.tsx @@ -25,7 +25,7 @@ import { ML_JOB_ID } from '../../../../common/constants'; import { UptimeRefreshContext, UptimeSettingsContext } from '../../../contexts'; import { useGetUrlParams } from '../../../hooks'; import { getDynamicSettings } from '../../../state/actions/dynamic_settings'; -import { useMonitorId } from '../../../hooks/use_monitor'; +import { useMonitorId } from '../../../hooks'; interface Props { onClose: () => void; diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx similarity index 98% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx index e053ca733cb8c..4963a901f0ecc 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_integeration.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_integeration.tsx @@ -21,7 +21,7 @@ import * as labels from './translations'; import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public'; import { ManageMLJobComponent } from './manage_ml_job'; import { JobStat } from '../../../../../../../plugins/ml/common/types/data_recognizer'; -import { useMonitorId } from '../../../hooks/use_monitor'; +import { useMonitorId } from '../../../hooks'; export const MLIntegrationComponent = () => { const [isMlFlyoutOpen, setIsMlFlyoutOpen] = useState(false); diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_job_link.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_job_link.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/ml_job_link.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/ml_job_link.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/translations.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/translations.tsx similarity index 95% rename from x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/translations.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ml/translations.tsx index 32374674771e8..bcc3fca770652 100644 --- a/x-pack/legacy/plugins/uptime/public/components/monitor_details/ml/translations.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ml/translations.tsx @@ -96,13 +96,6 @@ export const MANAGE_ANOMALY_DETECTION = i18n.translate( } ); -export const VIEW_EXISTING_JOB = i18n.translate( - 'xpack.uptime.ml.enableAnomalyDetectionPanel.callout.jobExistsDescription.viewJobLinkText', - { - defaultMessage: 'View existing job', - } -); - export const ML_MANAGEMENT_PAGE = i18n.translate( 'xpack.uptime.ml.enableAnomalyDetectionPanel.manageMLJobDescription.mlJobsPageLinkText', { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_charts.tsx similarity index 68% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_charts.tsx index c5edd0fd85977..f9cc1aa52b902 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_charts.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_charts.tsx @@ -6,7 +6,8 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { PingHistogram, DurationChart } from '../connected'; +import { PingHistogram } from './ping_histogram/ping_histogram_container'; +import { MonitorDuration } from './monitor_duration/monitor_duration_container'; interface MonitorChartsProps { monitorId: string; @@ -16,10 +17,10 @@ export const MonitorCharts = ({ monitorId }: MonitorChartsProps) => { return ( - + - + ); diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/index.ts new file mode 100644 index 0000000000000..aa3230a3f9bc0 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { MonitorDuration } from './monitor_duration_container'; +export { MonitorDurationComponent } from './monitor_duration'; diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration.tsx new file mode 100644 index 0000000000000..af1c8dbdc49e3 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; +import { LocationDurationLine } from '../../../../common/types'; +import { MLIntegrationComponent } from '../ml/ml_integeration'; +import { AnomalyRecords } from '../../../state/actions'; +import { DurationChartComponent } from '../../common/charts'; + +interface DurationChartProps { + loading: boolean; + hasMLJob: boolean; + anomalies: AnomalyRecords | null; + locationDurationLines: LocationDurationLine[]; +} + +/** + * This chart is intended to visualize monitor duration performance over time to + * the users in a helpful way. Its x-axis is based on a timeseries, the y-axis is in + * milliseconds. + * @param props The props required for this component to render properly + */ +export const MonitorDurationComponent = ({ + locationDurationLines, + anomalies, + loading, + hasMLJob, +}: DurationChartProps) => { + return ( + + + + +

+ {hasMLJob ? ( + + ) : ( + + )} +

+
+
+ + + +
+ +
+ ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx similarity index 91% rename from x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx index 40480905350af..7e39b977f1271 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/charts/monitor_duration.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_duration/monitor_duration_container.tsx @@ -12,7 +12,6 @@ import { getMLCapabilitiesAction, getMonitorDurationAction, } from '../../../state/actions'; -import { DurationChartComponent } from '../../functional/charts'; import { anomaliesSelector, hasMLFeatureAvailable, @@ -22,12 +21,10 @@ import { import { UptimeRefreshContext } from '../../../contexts'; import { getMLJobId } from '../../../state/api/ml_anomaly'; import { JobStat } from '../../../../../../../plugins/ml/common/types/data_recognizer'; +import { MonitorDurationComponent } from './monitor_duration'; +import { MonitorIdParam } from '../../../../common/types'; -interface Props { - monitorId: string; -} - -export const DurationChart: React.FC = ({ monitorId }: Props) => { +export const MonitorDuration: React.FC = ({ monitorId }) => { const { dateRangeStart, dateRangeEnd, @@ -75,7 +72,7 @@ export const DurationChart: React.FC = ({ monitorId }: Props) => { }, [dispatch]); return ( - { let monitorLocations: MonitorLocation[]; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/index.ts similarity index 64% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/index.ts index 385788cc825a0..e95f14472e9e8 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/index.ts @@ -5,5 +5,8 @@ */ export { MonitorStatusBarComponent } from './monitor_status_bar'; -export { MonitorStatusDetailsComponent } from './monitor_status_details'; +export { MonitorStatusDetailsComponent } from './status_details'; export { StatusByLocations } from './monitor_status_bar/status_by_location'; + +export { MonitorStatusDetails } from './status_details_container'; +export { MonitorStatusBar } from './monitor_status_bar/status_bar_container'; diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/index.ts new file mode 100644 index 0000000000000..3c861412a39e9 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export { MonitorSSLCertificate } from './ssl_certificate'; +export { MonitorStatusBarComponent } from './status_bar'; +export { MonitorStatusBar } from './status_bar_container'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_ssl_certificate.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/ssl_certificate.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar.tsx similarity index 95% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar.tsx index ac3cedc517995..36159dc29eccd 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/monitor_status_bar.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar.tsx @@ -14,7 +14,7 @@ import { EuiFlexGroup, EuiFlexItem, } from '@elastic/eui'; -import { MonitorSSLCertificate } from './monitor_ssl_certificate'; +import { MonitorSSLCertificate } from './ssl_certificate'; import * as labels from './translations'; import { StatusByLocations } from './status_by_location'; import { Ping } from '../../../../../common/runtime_types'; @@ -22,7 +22,7 @@ import { MonitorLocations } from '../../../../../common/runtime_types'; interface MonitorStatusBarProps { monitorId: string; - monitorStatus: Ping; + monitorStatus: Ping | null; monitorLocations: MonitorLocations; } diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar_container.tsx new file mode 100644 index 0000000000000..9562295437515 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_bar_container.tsx @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useContext, useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { monitorLocationsSelector, monitorStatusSelector } from '../../../../state/selectors'; +import { MonitorStatusBarComponent } from './index'; +import { getMonitorStatusAction } from '../../../../state/actions'; +import { useGetUrlParams } from '../../../../hooks'; +import { UptimeRefreshContext } from '../../../../contexts'; +import { MonitorIdParam } from '../../../../../common/types'; +import { AppState } from '../../../../state'; + +export const MonitorStatusBar: React.FC = ({ monitorId }) => { + const { lastRefresh } = useContext(UptimeRefreshContext); + + const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams(); + + const dispatch = useDispatch(); + + const monitorStatus = useSelector(monitorStatusSelector); + const monitorLocations = useSelector((state: AppState) => + monitorLocationsSelector(state, monitorId) + ); + + useEffect(() => { + dispatch(getMonitorStatusAction({ dateStart, dateEnd, monitorId })); + }, [monitorId, dateStart, dateEnd, lastRefresh, dispatch]); + + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/status_by_location.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_by_location.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/status_by_location.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/status_by_location.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/translations.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/translations.ts similarity index 99% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/translations.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/translations.ts index 1c2844f4f6ccf..f60a1ceeaafb8 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_bar/translations.ts +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/monitor_status_bar/translations.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import { i18n } from '@kbn/i18n'; export const healthStatusMessageAriaLabel = i18n.translate( diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx similarity index 97% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx index 7dea73da7bba0..ebd16b05ecb4a 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/monitor_status_details.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details.tsx @@ -10,7 +10,7 @@ import styled from 'styled-components'; import { LocationMap } from '../location_map'; import { UptimeRefreshContext } from '../../../contexts'; import { MonitorLocations } from '../../../../common/runtime_types'; -import { MonitorStatusBar } from '../../connected'; +import { MonitorStatusBar } from './monitor_status_bar'; interface MonitorStatusDetailsProps { monitorId: string; diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details_container.tsx new file mode 100644 index 0000000000000..251f3562f9d1a --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/status_details_container.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useContext, useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useGetUrlParams } from '../../../hooks'; +import { monitorLocationsSelector } from '../../../state/selectors'; +import { getMonitorLocationsAction } from '../../../state/actions/monitor'; +import { MonitorStatusDetailsComponent } from './index'; +import { UptimeRefreshContext } from '../../../contexts'; +import { AppState } from '../../../state'; +import { MonitorIdParam } from '../../../../common/types'; + +export const MonitorStatusDetails: React.FC = ({ monitorId }) => { + const { lastRefresh } = useContext(UptimeRefreshContext); + + const { dateRangeStart: dateStart, dateRangeEnd: dateEnd } = useGetUrlParams(); + + const dispatch = useDispatch(); + const monitorLocations = useSelector((state: AppState) => + monitorLocationsSelector(state, monitorId) + ); + + useEffect(() => { + dispatch(getMonitorLocationsAction({ dateStart, dateEnd, monitorId })); + }, [monitorId, dateStart, dateEnd, lastRefresh, dispatch]); + + return ( + + ); +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/translations.ts similarity index 99% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/translations.ts index 1c2844f4f6ccf..f60a1ceeaafb8 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_status_details/translations.ts +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/monitor_status_details/translations.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + import { i18n } from '@kbn/i18n'; export const healthStatusMessageAriaLabel = i18n.translate( diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/index.ts similarity index 80% rename from x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/index.ts index 95ced104e5188..c980b41167d0c 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/pings/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { PingList, PingListProps } from './ping_list'; +export { PingHistogram } from './ping_histogram_container'; diff --git a/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.tsx new file mode 100644 index 0000000000000..c0e17966f5b9f --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_histogram/ping_histogram_container.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { PingHistogramComponent } from '../../common/charts'; +import { getPingHistogram } from '../../../state/actions'; +import { selectPingHistogram } from '../../../state/selectors'; +import { useGetUrlParams } from '../../../hooks'; +import { useMonitorId } from '../../../hooks'; +import { ResponsiveWrapperProps, withResponsiveWrapper } from '../../common/higher_order'; + +interface Props { + height: string; +} + +const Container: React.FC = ({ height }) => { + const { + statusFilter, + absoluteDateRangeStart, + absoluteDateRangeEnd, + dateRangeStart: dateStart, + dateRangeEnd: dateEnd, + } = useGetUrlParams(); + + const dispatch = useDispatch(); + const monitorId = useMonitorId(); + + const { loading, data, esKuery, lastRefresh } = useSelector(selectPingHistogram); + + useEffect(() => { + dispatch(getPingHistogram({ monitorId, dateStart, dateEnd, statusFilter, filters: esKuery })); + }, [dateStart, dateEnd, monitorId, statusFilter, lastRefresh, esKuery, dispatch]); + return ( + + ); +}; + +export const PingHistogram = withResponsiveWrapper(Container); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/doc_link_body.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/expanded_row.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/__snapshots__/ping_list.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/doc_link_body.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/doc_link_body.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/doc_link_body.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/doc_link_body.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/expanded_row.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/expanded_row.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/expanded_row.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/ping_list.test.tsx similarity index 99% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/ping_list.test.tsx index ec256a886aa16..cb8413ba08a81 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/__tests__/ping_list.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/__tests__/ping_list.test.tsx @@ -7,8 +7,8 @@ import React from 'react'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { PingListComponent, toggleDetails } from '../ping_list'; -import { ExpandedRowMap } from '../../monitor_list/types'; import { Ping, PingsResponse } from '../../../../../common/runtime_types'; +import { ExpandedRowMap } from '../../../overview/monitor_list/types'; describe('PingList component', () => { let response: PingsResponse; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/doc_link_body.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/doc_link_body.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/doc_link_body.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/doc_link_body.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/expanded_row.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/expanded_row.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/expanded_row.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/index.tsx similarity index 85% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/index.tsx index 808f3f90ef015..7fc19bbc9622b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/index.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/index.tsx @@ -5,3 +5,4 @@ */ export { PingListComponent } from './ping_list'; +export { PingList } from './ping_list_container'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/location_name.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/location_name.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/location_name.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/location_name.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx similarity index 98% rename from x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx index 934dfd961f9e0..5dfc1c0647430 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/ping_list/ping_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list.tsx @@ -26,9 +26,9 @@ import styled from 'styled-components'; import { Ping, GetPingsParams, DateRange } from '../../../../common/runtime_types'; import { convertMicrosecondsToMilliseconds as microsToMillis } from '../../../lib/helper'; import { LocationName } from './location_name'; -import { Pagination } from './../monitor_list'; +import { Pagination } from '../../overview/monitor_list'; import { PingListExpandedRowComponent } from './expanded_row'; -import { PingListProps } from '../../connected/pings'; +import { PingListProps } from './ping_list_container'; export const AllLocationOption = { 'data-test-subj': 'xpack.uptime.pingList.locationOptions.all', @@ -139,7 +139,7 @@ export const PingListComponent = (props: Props) => { })) ); - const hasStatus: boolean = pings.reduce( + const hasStatus = pings.reduce( (hasHttpStatus: boolean, currentPing) => hasHttpStatus || !!currentPing.http?.response?.status_code, false diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list_container.tsx similarity index 96% rename from x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx rename to x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list_container.tsx index 5b32a623495f1..3c3caab365e3a 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/pings/ping_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/monitor/ping_list/ping_list_container.tsx @@ -10,7 +10,7 @@ import { selectPingList } from '../../../state/selectors'; import { getPings } from '../../../state/actions'; import { GetPingsParams } from '../../../../common/runtime_types'; import { UptimeSettingsContext } from '../../../contexts'; -import { PingListComponent } from '../../functional'; +import { PingListComponent } from './index'; export interface PingListProps { monitorId: string; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/overview_page_parsing_error_callout.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/parsing_error_callout.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/overview_page_parsing_error_callout.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/parsing_error_callout.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/snapshot.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/snapshot.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot_heading.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/snapshot_heading.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/__snapshots__/snapshot_heading.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/__snapshots__/snapshot_heading.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/overview_page_parsing_error_callout.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/parsing_error_callout.test.tsx similarity index 76% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/overview_page_parsing_error_callout.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/parsing_error_callout.test.tsx index fbe55dfedc2fc..01204c33b79d5 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/overview_page_parsing_error_callout.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/parsing_error_callout.test.tsx @@ -6,13 +6,13 @@ import React from 'react'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { OverviewPageParsingErrorCallout } from '../overview_page_parsing_error_callout'; +import { ParsingErrorCallout } from '../parsing_error_callout'; describe('OverviewPageParsingErrorCallout', () => { it('renders without errors when a valid error is provided', () => { expect( shallowWithIntl( - ) @@ -21,6 +21,6 @@ describe('OverviewPageParsingErrorCallout', () => { it('renders without errors when an error with no message is provided', () => { const error: any = {}; - expect(shallowWithIntl()).toMatchSnapshot(); + expect(shallowWithIntl()).toMatchSnapshot(); }); }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot.test.tsx similarity index 92% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot.test.tsx index 214b0394369f7..cfcab673dcb35 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import { Snapshot } from '../../../../common/runtime_types'; -import { SnapshotComponent } from '../snapshot'; +import { SnapshotComponent } from '../snapshot/snapshot'; describe('Snapshot component', () => { const snapshot: Snapshot = { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot_heading.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot_heading.test.tsx similarity index 93% rename from x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot_heading.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot_heading.test.tsx index 70d082b26d653..805c116ef538a 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/__tests__/snapshot_heading.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/__tests__/snapshot_heading.test.tsx @@ -6,7 +6,7 @@ import { shallowWithIntl } from 'test_utils/enzyme_helpers'; import React from 'react'; -import { SnapshotHeading } from '../snapshot_heading'; +import { SnapshotHeading } from '../snapshot/snapshot_heading'; describe('SnapshotHeading', () => { it('renders custom heading for no down monitors', () => { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/__tests__/alert_monitor_status.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/__tests__/alert_monitor_status.test.tsx similarity index 98% rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/__tests__/alert_monitor_status.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/__tests__/alert_monitor_status.test.tsx index af8d17d1fc242..8f33b6f652b9d 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/__tests__/alert_monitor_status.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/__tests__/alert_monitor_status.test.tsx @@ -14,8 +14,8 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers'; describe('alert monitor status component', () => { describe('handleAlertFieldNumberChange', () => { - let mockSetIsInvalid: jest.Mock; - let mockSetFieldValue: jest.Mock; + let mockSetIsInvalid: jest.Mock; + let mockSetFieldValue: jest.Mock; beforeEach(() => { mockSetIsInvalid = jest.fn(); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/alert_monitor_status.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alert_monitor_status.tsx similarity index 99% rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/alert_monitor_status.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alert_monitor_status.tsx index b86e85f35b17d..83892bf23dced 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/alert_monitor_status.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alert_monitor_status.tsx @@ -19,7 +19,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { DataPublicPluginSetup } from 'src/plugins/data/public'; -import { KueryBar } from '../../connected/kuerybar/kuery_bar_container'; +import { KueryBar } from '..'; interface AlertFieldNumberProps { 'aria-label': string; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/alert_monitor_status.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx similarity index 86% rename from x-pack/legacy/plugins/uptime/public/components/connected/alerts/alert_monitor_status.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx index 1529ab6db8875..9dd27db0be607 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/alert_monitor_status.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/alert_monitor_status.tsx @@ -7,8 +7,8 @@ import React from 'react'; import { useSelector } from 'react-redux'; import { DataPublicPluginSetup } from 'src/plugins/data/public'; -import { selectMonitorStatusAlert } from '../../../state/selectors'; -import { AlertMonitorStatusComponent } from '../../functional/alerts/alert_monitor_status'; +import { selectMonitorStatusAlert } from '../../../../state/selectors'; +import { AlertMonitorStatusComponent } from '../index'; interface Props { autocomplete: DataPublicPluginSetup['autocomplete']; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/index.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/connected/alerts/index.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/index.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/toggle_alert_flyout_button.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx similarity index 80% rename from x-pack/legacy/plugins/uptime/public/components/connected/alerts/toggle_alert_flyout_button.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx index 43b0be45365a1..45ba72d76fba6 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/toggle_alert_flyout_button.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx @@ -6,8 +6,8 @@ import React from 'react'; import { useDispatch } from 'react-redux'; -import { ToggleAlertFlyoutButtonComponent } from '../../functional'; -import { setAlertFlyoutVisible } from '../../../state/actions'; +import { setAlertFlyoutVisible } from '../../../../state/actions'; +import { ToggleAlertFlyoutButtonComponent } from '../index'; export const ToggleAlertFlyoutButton = () => { const dispatch = useDispatch(); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/uptime_alerts_flyout_wrapper.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/uptime_alerts_flyout_wrapper.tsx similarity index 83% rename from x-pack/legacy/plugins/uptime/public/components/connected/alerts/uptime_alerts_flyout_wrapper.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/uptime_alerts_flyout_wrapper.tsx index a49468ad3dd06..7bfd44a762455 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/alerts/uptime_alerts_flyout_wrapper.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/alerts_containers/uptime_alerts_flyout_wrapper.tsx @@ -6,9 +6,9 @@ import React from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { UptimeAlertsFlyoutWrapperComponent } from '../../functional'; -import { setAlertFlyoutVisible } from '../../../state/actions'; -import { selectAlertFlyoutVisibility } from '../../../state/selectors'; +import { setAlertFlyoutVisible } from '../../../../state/actions'; +import { selectAlertFlyoutVisibility } from '../../../../state/selectors'; +import { UptimeAlertsFlyoutWrapperComponent } from '../index'; interface Props { alertTypeId?: string; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/index.ts similarity index 93% rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/index.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/index.ts index 275333b60c5ee..5ca0f4c3fe8a7 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/index.ts @@ -8,3 +8,4 @@ export { AlertMonitorStatusComponent } from './alert_monitor_status'; export { ToggleAlertFlyoutButtonComponent } from './toggle_alert_flyout_button'; export { UptimeAlertsContextProvider } from './uptime_alerts_context_provider'; export { UptimeAlertsFlyoutWrapperComponent } from './uptime_alerts_flyout_wrapper'; +export * from './alerts_containers'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/toggle_alert_flyout_button.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/toggle_alert_flyout_button.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/uptime_alerts_context_provider.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/uptime_alerts_context_provider.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/uptime_alerts_context_provider.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/uptime_alerts_context_provider.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/alerts/uptime_alerts_flyout_wrapper.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/alerts/uptime_alerts_flyout_wrapper.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/alerts/uptime_alerts_flyout_wrapper.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/alerts/uptime_alerts_flyout_wrapper.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/data_or_index_missing.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/__snapshots__/empty_state.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/empty_state/__tests__/data_or_index_missing.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/data_or_index_missing.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/empty_state/__tests__/data_or_index_missing.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/data_or_index_missing.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/empty_state/__tests__/empty_state.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/empty_state.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/empty_state/__tests__/empty_state.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/__tests__/empty_state.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/empty_state/data_or_index_missing.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/data_or_index_missing.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/empty_state/data_or_index_missing.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/data_or_index_missing.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/empty_state/empty_state.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/empty_state/empty_state.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/empty_state/empty_state.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state_container.tsx similarity index 95% rename from x-pack/legacy/plugins/uptime/public/components/connected/empty_state/empty_state.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state_container.tsx index b0868af70480a..9a62cb9cdaeee 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/empty_state/empty_state.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state_container.tsx @@ -8,7 +8,7 @@ import React, { useContext, useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { indexStatusAction } from '../../../state/actions'; import { indexStatusSelector, selectDynamicSettings } from '../../../state/selectors'; -import { EmptyStateComponent } from '../../functional/empty_state/empty_state'; +import { EmptyStateComponent } from './index'; import { UptimeRefreshContext } from '../../../contexts'; import { getDynamicSettings } from '../../../state/actions/dynamic_settings'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/empty_state/empty_state_error.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/empty_state/empty_state_error.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state_error.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/empty_state/empty_state_loading.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state_loading.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/empty_state/empty_state_loading.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/empty_state/empty_state_loading.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/index.ts new file mode 100644 index 0000000000000..9f2a668f4c3a5 --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/overview/empty_state/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { EmptyStateComponent } from './empty_state'; +export { EmptyState } from './empty_state_container'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/filter_popover.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/filter_status_button.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/filter_status_button.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/filter_status_button.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/filter_status_button.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/parse_filter_map.test.ts.snap b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/parse_filter_map.test.ts.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/__snapshots__/parse_filter_map.test.ts.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/__snapshots__/parse_filter_map.test.ts.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/filter_popover.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/filter_popover.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/filter_popover.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/filter_popover.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/filter_status_button.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/filter_status_button.test.tsx similarity index 93% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/filter_status_button.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/filter_status_button.test.tsx index 1813229a97d1b..2ad4d971cf3b0 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/filter_status_button.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/filter_status_button.test.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { FilterStatusButton, FilterStatusButtonProps } from '../filter_status_button'; -import { shallowWithRouter } from '../../../../lib/'; +import { shallowWithRouter } from '../../../../lib'; describe('FilterStatusButton', () => { let props: FilterStatusButtonProps; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/parse_filter_map.test.ts b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/parse_filter_map.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/parse_filter_map.test.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/parse_filter_map.test.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/toggle_selected_item.test.ts b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/toggle_selected_item.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/__tests__/toggle_selected_item.test.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/__tests__/toggle_selected_item.test.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/filter_group.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_group.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/filter_group.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_group.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/filter_group/filter_group_container.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_group_container.tsx similarity index 94% rename from x-pack/legacy/plugins/uptime/public/components/connected/filter_group/filter_group_container.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_group_container.tsx index 569c6bb883cbd..3612604fdf116 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/filter_group/filter_group_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_group_container.tsx @@ -7,10 +7,10 @@ import React, { useContext, useEffect } from 'react'; import { connect } from 'react-redux'; import { useUrlParams } from '../../../hooks'; -import { parseFiltersMap } from '../../functional/filter_group/parse_filter_map'; +import { parseFiltersMap } from './parse_filter_map'; import { AppState } from '../../../state'; import { fetchOverviewFilters, GetOverviewFiltersPayload } from '../../../state/actions'; -import { FilterGroupComponent } from '../../functional/filter_group'; +import { FilterGroupComponent } from './index'; import { OverviewFilters } from '../../../../common/runtime_types/overview_filters'; import { UptimeRefreshContext } from '../../../contexts'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/filter_popover.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_popover.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/filter_popover.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_popover.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/filter_status_button.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_status_button.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/filter_status_button.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/filter_status_button.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/index.ts similarity index 84% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/index.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/index.ts index 2aae026144d8f..933fddf1cde27 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/index.ts @@ -5,3 +5,4 @@ */ export { FilterGroupComponent } from './filter_group'; +export { FilterGroup } from './filter_group_container'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/parse_filter_map.ts b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/parse_filter_map.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/parse_filter_map.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/parse_filter_map.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/toggle_selected_item.ts b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/toggle_selected_item.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/toggle_selected_item.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/toggle_selected_item.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/filter_group/uptime_filter_button.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/filter_group/uptime_filter_button.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/filter_group/uptime_filter_button.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/filter_group/uptime_filter_button.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/overview/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/index.ts new file mode 100644 index 0000000000000..ac293e9233c8c --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/overview/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export * from './monitor_list'; +export * from './empty_state'; +export * from './filter_group'; +export * from './alerts'; +export * from './snapshot'; +export * from './kuery_bar'; + +export { ParsingErrorCallout } from './parsing_error_callout'; diff --git a/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/index.ts new file mode 100644 index 0000000000000..60801a0ab705a --- /dev/null +++ b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/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; + * you may not use this file except in compliance with the Elastic License. + */ + +export { KueryBarComponent } from './kuery_bar'; +export { KueryBar } from './kuery_bar_container'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/kuery_bar.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/kuery_bar.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/kuery_bar.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/kuerybar/kuery_bar_container.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/kuery_bar_container.tsx similarity index 90% rename from x-pack/legacy/plugins/uptime/public/components/connected/kuerybar/kuery_bar_container.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/kuery_bar_container.tsx index 132ae57b5154f..5e1e184b2d6e6 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/kuerybar/kuery_bar_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/kuery_bar_container.tsx @@ -8,7 +8,7 @@ import { connect } from 'react-redux'; import { AppState } from '../../../state'; import { selectIndexPattern } from '../../../state/selectors'; import { getIndexPattern } from '../../../state/actions'; -import { KueryBarComponent } from '../../functional/kuery_bar/kuery_bar'; +import { KueryBarComponent } from './kuery_bar'; const mapStateToProps = (state: AppState) => ({ ...selectIndexPattern(state) }); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/click_outside.js b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/click_outside.js similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/click_outside.js rename to x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/click_outside.js diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/index.d.ts b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/index.d.ts similarity index 95% rename from x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/index.d.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/index.d.ts index c9f43b3a620bd..defde6203a8c5 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/index.d.ts +++ b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/index.d.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Component } from 'react'; +import React from 'react'; interface TypeaheadProps { onChange: (inputValue: string, selectionStart: number) => void; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/index.js b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/index.js similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/index.js rename to x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/index.js diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/suggestion.js b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/suggestion.js similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/suggestion.js rename to x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/suggestion.js diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/suggestions.js b/x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/suggestions.js similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/kuery_bar/typeahead/suggestions.js rename to x-pack/legacy/plugins/uptime/public/components/overview/kuery_bar/typeahead/suggestions.js diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_status_column.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list_status_column.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_list_status_column.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_list_status_column.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_page_link.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_page_link.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/__snapshots__/monitor_page_link.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/__snapshots__/monitor_page_link.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_page_size_select.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list_page_size_select.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_page_size_select.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list_page_size_select.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_status_column.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list_status_column.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_list_status_column.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_list_status_column.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_page_link.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_page_link.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/monitor_page_link.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/monitor_page_link.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/parse_timestamp.test.ts b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/parse_timestamp.test.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/__tests__/parse_timestamp.test.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/__tests__/parse_timestamp.test.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/index.ts similarity index 69% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/index.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/index.ts index 2dc43050f9515..45e8822a317a4 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/index.ts @@ -7,3 +7,5 @@ export { MonitorListComponent } from './monitor_list'; export { Criteria, Pagination } from './types'; export { LocationLink } from './monitor_list_drawer'; +export { MonitorListDrawer } from './monitor_list_drawer/list_drawer_container'; +export { ActionsPopover } from './monitor_list_drawer/actions_popover/actions_popover_container'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx similarity index 97% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx index 6705101ccd572..18e2e2437e147 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list.tsx @@ -22,13 +22,13 @@ import { HistogramPoint, FetchMonitorStatesQueryArgs } from '../../../../common/ import { MonitorSummary } from '../../../../common/runtime_types'; import { MonitorListStatusColumn } from './monitor_list_status_column'; import { ExpandedRowMap } from './types'; -import { MonitorBarSeries } from '../charts'; +import { MonitorBarSeries } from '../../common/charts'; import { MonitorPageLink } from './monitor_page_link'; import { OverviewPageLink } from './overview_page_link'; import * as labels from './translations'; -import { MonitorListDrawer } from '../../connected'; import { MonitorListPageSizeSelect } from './monitor_list_page_size_select'; -import { MonitorListProps } from '../../connected/monitor/monitor_list'; +import { MonitorListDrawer } from './monitor_list_drawer/list_drawer_container'; +import { MonitorListProps } from './monitor_list_container'; import { MonitorList } from '../../../state/reducers/monitor_list'; import { useUrlParams } from '../../../hooks'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/monitor_list.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_container.tsx similarity index 93% rename from x-pack/legacy/plugins/uptime/public/components/connected/monitor/monitor_list.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_container.tsx index c9457664566b7..5bfe6ff0c5b4f 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/monitor_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_container.tsx @@ -9,7 +9,7 @@ import { useSelector, useDispatch } from 'react-redux'; import { getMonitorList } from '../../../state/actions'; import { FetchMonitorStatesQueryArgs } from '../../../../common/runtime_types'; import { monitorListSelector } from '../../../state/selectors'; -import { MonitorListComponent } from '../../functional/monitor_list'; +import { MonitorListComponent } from './index'; export interface MonitorListProps { filters?: string; @@ -18,13 +18,16 @@ export interface MonitorListProps { export const MonitorList: React.FC = props => { const dispatch = useDispatch(); + const dispatchCallback = useCallback( (params: FetchMonitorStatesQueryArgs) => { dispatch(getMonitorList(params)); }, [dispatch] ); + const monitorListState = useSelector(monitorListSelector); + return ( ); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_group.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_group.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_group.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_group.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_link.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_link.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_link.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/integration_link.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_list_drawer.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_list.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_list.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_list.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_list.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_row.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_row.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_row.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/monitor_status_row.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/__snapshots__/most_recent_error.test.tsx.snap diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/data.json b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/data.json similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/data.json rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/data.json diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx similarity index 94% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx index 48fa2c9766681..25cf400bcd0fd 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/integration_group.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { MonitorSummary } from '../../../../../../common/runtime_types'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { IntegrationGroup } from '../integration_group'; +import { IntegrationGroup } from '../actions_popover/integration_group'; describe('IntegrationGroup', () => { let summary: MonitorSummary; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_link.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/integration_link.test.tsx similarity index 93% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_link.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/integration_link.test.tsx index ba313f255f13d..8ee83bc38957b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/integration_link.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/integration_link.test.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { IntegrationLink } from '../integration_link'; +import { IntegrationLink } from '../actions_popover/integration_link'; import { shallowWithIntl } from 'test_utils/enzyme_helpers'; describe('IntegrationLink component', () => { diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/monitor_list_drawer.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/monitor_status_list.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_status_row.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/monitor_status_row.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/monitor_status_row.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/monitor_status_row.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/most_recent_error.test.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/most_recent_error.test.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/__tests__/most_recent_error.test.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/__tests__/most_recent_error.test.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_actions_popover.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover.tsx similarity index 89% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_actions_popover.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover.tsx index c57ecbaa4d3ed..e86e6b309214f 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_actions_popover.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover.tsx @@ -9,20 +9,20 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { EuiPopover, EuiButton } from '@elastic/eui'; import { IntegrationGroup } from './integration_group'; -import { MonitorSummary } from '../../../../../common/runtime_types'; -import { toggleIntegrationsPopover, PopoverState } from '../../../../state/actions'; +import { MonitorSummary } from '../../../../../../common/runtime_types'; +import { toggleIntegrationsPopover, PopoverState } from '../../../../../state/actions'; -interface MonitorListActionsPopoverProps { +interface ActionsPopoverProps { summary: MonitorSummary; popoverState: PopoverState | null; togglePopoverIsVisible: typeof toggleIntegrationsPopover; } -export const MonitorListActionsPopoverComponent = ({ +export const ActionsPopoverComponent = ({ summary, popoverState, togglePopoverIsVisible, -}: MonitorListActionsPopoverProps) => { +}: ActionsPopoverProps) => { const popoverId = `${summary.monitor_id}_popover`; const monitorUrl: string | undefined = get(summary, 'state.url.full', undefined); diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/drawer_popover_container.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover_container.tsx similarity index 63% rename from x-pack/legacy/plugins/uptime/public/components/connected/monitor/drawer_popover_container.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover_container.tsx index be29e12f716a9..b1c25ddd7a338 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/drawer_popover_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/actions_popover_container.tsx @@ -5,10 +5,10 @@ */ import { connect } from 'react-redux'; -import { AppState } from '../../../state'; -import { isIntegrationsPopupOpen } from '../../../state/selectors'; -import { PopoverState, toggleIntegrationsPopover } from '../../../state/actions'; -import { MonitorListActionsPopoverComponent } from '../../functional/monitor_list/monitor_list_drawer'; +import { AppState } from '../../../../../state'; +import { isIntegrationsPopupOpen } from '../../../../../state/selectors'; +import { PopoverState, toggleIntegrationsPopover } from '../../../../../state/actions'; +import { ActionsPopoverComponent } from '../index'; const mapStateToProps = (state: AppState) => ({ popoverState: isIntegrationsPopupOpen(state), @@ -20,7 +20,4 @@ const mapDispatchToProps = (dispatch: any) => ({ }, }); -export const MonitorListActionsPopover = connect( - mapStateToProps, - mapDispatchToProps -)(MonitorListActionsPopoverComponent); +export const ActionsPopover = connect(mapStateToProps, mapDispatchToProps)(ActionsPopoverComponent); diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_group.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_group.tsx similarity index 98% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_group.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_group.tsx index cc06b9a2306c7..bbcba7238748d 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_group.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_group.tsx @@ -18,9 +18,9 @@ import { getLoggingContainerHref, getLoggingIpHref, getLoggingKubernetesHref, -} from '../../../../lib/helper'; -import { MonitorSummary } from '../../../../../common/runtime_types'; -import { UptimeSettingsContext } from '../../../../contexts'; +} from '../../../../../lib/helper'; +import { MonitorSummary } from '../../../../../../common/runtime_types'; +import { UptimeSettingsContext } from '../../../../../contexts'; interface IntegrationGroupProps { summary: MonitorSummary; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_link.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_link.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/integration_link.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_link.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/index.ts b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/index.ts similarity index 63% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/index.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/index.ts index 2933a71c2240b..32c722b806f2b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/index.ts +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/index.ts @@ -4,5 +4,5 @@ * you may not use this file except in compliance with the Elastic License. */ -export { LocationLink } from './location_link'; -export { MonitorListActionsPopoverComponent } from './monitor_list_actions_popover'; +export { LocationLink } from '../../../common/location_link'; +export { ActionsPopoverComponent } from './actions_popover/actions_popover'; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/list_drawer_container.tsx similarity index 72% rename from x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/list_drawer_container.tsx index 37a96ba0396aa..bec32ace27f2b 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/monitor/list_drawer_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/list_drawer_container.tsx @@ -6,13 +6,13 @@ import React, { useEffect } from 'react'; import { connect } from 'react-redux'; -import { AppState } from '../../../state'; -import { monitorDetailsSelector } from '../../../state/selectors'; -import { MonitorDetailsActionPayload } from '../../../state/actions/types'; -import { getMonitorDetailsAction } from '../../../state/actions/monitor'; -import { MonitorListDrawerComponent } from '../../functional/monitor_list/monitor_list_drawer/monitor_list_drawer'; -import { useGetUrlParams } from '../../../hooks'; -import { MonitorDetails, MonitorSummary } from '../../../../common/runtime_types'; +import { AppState } from '../../../../state'; +import { monitorDetailsSelector } from '../../../../state/selectors'; +import { MonitorDetailsActionPayload } from '../../../../state/actions/types'; +import { getMonitorDetailsAction } from '../../../../state/actions/monitor'; +import { MonitorListDrawerComponent } from './monitor_list_drawer'; +import { useGetUrlParams } from '../../../../hooks'; +import { MonitorDetails, MonitorSummary } from '../../../../../common/runtime_types'; interface ContainerProps { summary: MonitorSummary; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx similarity index 93% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx index 6dc9ebbef1287..8e97ce4d692d7 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_list_drawer.tsx @@ -10,7 +10,7 @@ import { EuiLink, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText } from import { MostRecentError } from './most_recent_error'; import { MonitorStatusList } from './monitor_status_list'; import { MonitorDetails, MonitorSummary } from '../../../../../common/runtime_types'; -import { MonitorListActionsPopover } from '../../../connected'; +import { ActionsPopover } from './actions_popover/actions_popover_container'; const ContainerDiv = styled.div` padding: 10px; @@ -48,7 +48,7 @@ export function MonitorListDrawerComponent({ summary, monitorDetails }: MonitorL - + diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_list.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_list.tsx similarity index 97% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_list.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_list.tsx index 8a46167dcd3bc..cd1a5a95b8adb 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_list.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_list.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { get, capitalize } from 'lodash'; import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { LocationLink } from './location_link'; +import { LocationLink } from '../../../common/location_link'; import { MonitorStatusRow } from './monitor_status_row'; import { Check } from '../../../../../common/runtime_types'; import { STATUS, UNNAMED_LOCATION } from '../../../../../common/constants'; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_row.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_row.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/monitor_status_row.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/monitor_status_row.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/most_recent_error.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_drawer/most_recent_error.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/most_recent_error.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_page_size_select.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_page_size_select.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_page_size_select.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_page_size_select.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_status_column.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_status_column.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_list_status_column.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_list_status_column.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_page_link.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_page_link.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/monitor_page_link.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/monitor_page_link.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/overview_page_link.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/overview_page_link.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/overview_page_link.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/overview_page_link.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/parse_timestamp.ts b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/parse_timestamp.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/parse_timestamp.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/parse_timestamp.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/translations.ts b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/translations.ts similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/translations.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/translations.ts diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/types.ts b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/types.ts similarity index 83% rename from x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/types.ts rename to x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/types.ts index a25603d3603d9..6a6cee4a7d96d 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/monitor_list/types.ts +++ b/x-pack/legacy/plugins/uptime/public/components/overview/monitor_list/types.ts @@ -4,13 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export interface CondensedCheck { - childStatuses: CondensedCheckStatus[]; - location: string | null; - status: string; - timestamp: string; -} - export interface CondensedCheckStatus { ip?: string | null; status: string; diff --git a/x-pack/legacy/plugins/uptime/public/components/connected/pages/overview_container.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/overview_container.tsx similarity index 74% rename from x-pack/legacy/plugins/uptime/public/components/connected/pages/overview_container.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/overview_container.tsx index 79aaa071507e1..d64e489c48076 100644 --- a/x-pack/legacy/plugins/uptime/public/components/connected/pages/overview_container.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/overview_container.tsx @@ -5,10 +5,10 @@ */ import { connect } from 'react-redux'; -import { OverviewPageComponent } from '../../../pages/overview'; -import { selectIndexPattern } from '../../../state/selectors'; -import { AppState } from '../../../state'; -import { setEsKueryString } from '../../../state/actions'; +import { OverviewPageComponent } from '../../pages/overview'; +import { selectIndexPattern } from '../../state/selectors'; +import { AppState } from '../../state'; +import { setEsKueryString } from '../../state/actions'; interface DispatchProps { setEsKueryFilters: typeof setEsKueryString; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/overview_page_parsing_error_callout.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/parsing_error_callout.tsx similarity index 89% rename from x-pack/legacy/plugins/uptime/public/components/functional/overview_page_parsing_error_callout.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/parsing_error_callout.tsx index b71a4f2f8646a..96ea14cdf9f37 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/overview_page_parsing_error_callout.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/parsing_error_callout.tsx @@ -13,13 +13,11 @@ interface HasMessage { message: string; } -interface OverviewPageParsingErrorCalloutProps { +interface ParsingErrorCalloutProps { error: HasMessage; } -export const OverviewPageParsingErrorCallout = ({ - error, -}: OverviewPageParsingErrorCalloutProps) => ( +export const ParsingErrorCallout = ({ error }: ParsingErrorCalloutProps) => ( = ({ height }: Props) => { + const { dateRangeStart, dateRangeEnd, statusFilter } = useGetUrlParams(); + + const { count, lastRefresh, loading, esKuery } = useSelector(snapshotDataSelector); + + const dispatch = useDispatch(); + + useEffect(() => { + dispatch( + getSnapshotCountAction({ dateRangeStart, dateRangeEnd, filters: esKuery, statusFilter }) + ); + }, [dateRangeStart, dateRangeEnd, esKuery, lastRefresh, statusFilter, dispatch]); + return ; +}; diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/snapshot_heading.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/snapshot/snapshot_heading.tsx similarity index 100% rename from x-pack/legacy/plugins/uptime/public/components/functional/snapshot_heading.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/snapshot/snapshot_heading.tsx diff --git a/x-pack/legacy/plugins/uptime/public/components/functional/status_panel.tsx b/x-pack/legacy/plugins/uptime/public/components/overview/status_panel.tsx similarity index 87% rename from x-pack/legacy/plugins/uptime/public/components/functional/status_panel.tsx rename to x-pack/legacy/plugins/uptime/public/components/overview/status_panel.tsx index 2c0be2aa15d6f..9edcb08a6d5b1 100644 --- a/x-pack/legacy/plugins/uptime/public/components/functional/status_panel.tsx +++ b/x-pack/legacy/plugins/uptime/public/components/overview/status_panel.tsx @@ -6,7 +6,8 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; -import { PingHistogram, Snapshot } from '../connected'; +import { PingHistogram } from '../monitor'; +import { Snapshot } from './snapshot/snapshot_container'; const STATUS_CHART_HEIGHT = '160px'; diff --git a/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx b/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx index c5a0ec4831798..137846de103b4 100644 --- a/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx +++ b/x-pack/legacy/plugins/uptime/public/contexts/uptime_settings_context.tsx @@ -7,7 +7,7 @@ import React, { createContext, useMemo } from 'react'; import { UptimeAppProps } from '../uptime_app'; import { CLIENT_DEFAULTS, CONTEXT_DEFAULTS } from '../../common/constants'; -import { CommonlyUsedRange } from '../components/functional/uptime_date_picker'; +import { CommonlyUsedRange } from '../components/common/uptime_date_picker'; import { useGetUrlParams } from '../hooks'; import { ILicense } from '../../../../../plugins/licensing/common/types'; diff --git a/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx b/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx index 85961003fce72..1ce00fe7ce3af 100644 --- a/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx +++ b/x-pack/legacy/plugins/uptime/public/hooks/__tests__/use_breadcrumbs.test.tsx @@ -11,7 +11,7 @@ import { mountWithRouter } from '../../lib'; import { OVERVIEW_ROUTE } from '../../../common/constants'; import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public'; import { UptimeUrlParams, getSupportedUrlParams } from '../../lib/helper'; -import { makeBaseBreadcrumb, useBreadcrumbs } from '../../hooks/use_breadcrumbs'; +import { makeBaseBreadcrumb, useBreadcrumbs } from '../use_breadcrumbs'; describe('useBreadcrumbs', () => { it('sets the given breadcrumbs', () => { diff --git a/x-pack/legacy/plugins/uptime/public/lib/alert_types/index.ts b/x-pack/legacy/plugins/uptime/public/lib/alert_types/index.ts index f764505a6d683..74160577cb0b1 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/alert_types/index.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/alert_types/index.ts @@ -6,7 +6,7 @@ // TODO: after NP migration is complete we should be able to remove this lint ignore comment // eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { AlertTypeModel } from '../../../../../../plugins/triggers_actions_ui/public/types'; +import { AlertTypeModel } from '../../../../../../plugins/triggers_actions_ui/public'; import { initMonitorStatusAlertType } from './monitor_status'; export type AlertTypeInitializer = (dependenies: { autocomplete: any }) => AlertTypeModel; diff --git a/x-pack/legacy/plugins/uptime/public/lib/alert_types/monitor_status.tsx b/x-pack/legacy/plugins/uptime/public/lib/alert_types/monitor_status.tsx index d059274159c7f..0624d20b197c0 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/alert_types/monitor_status.tsx +++ b/x-pack/legacy/plugins/uptime/public/lib/alert_types/monitor_status.tsx @@ -16,7 +16,7 @@ import { } from '../../../../../../plugins/triggers_actions_ui/public/types'; import { AlertTypeInitializer } from '.'; import { StatusCheckExecutorParamsType } from '../../../common/runtime_types'; -import { AlertMonitorStatus } from '../../components/connected/alerts'; +import { AlertMonitorStatus } from '../../components/overview/alerts/alerts_containers'; export const validate = (alertParams: any): ValidationResult => { const errors: Record = {}; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_chart_date_label.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_chart_date_label.ts index 126b1d85f749f..aa5a2b0f60e4f 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_chart_date_label.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_chart_date_label.ts @@ -11,7 +11,7 @@ import { CHART_FORMAT_LIMITS } from '../../../../common/constants'; /** * Generates an appropriate date formatting string intended for the y-axis * label of timeseries charts. The function will return day/month values for shorter - * timespans that cross the local date threshold, otherwise it estimates an appropriate + * time spans that cross the local date threshold, otherwise it estimates an appropriate * label for several different stops. * @param dateRangeStart the beginning of the date range * @param dateRangeEnd the end of the date range diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_label_format.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_label_format.ts index 668147fee8055..5957123e9257d 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_label_format.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/charts/get_label_format.ts @@ -49,7 +49,7 @@ const dateStops: Array<{ key: number; value: string }> = [ ]; /** - * Returns an appropriate label format bbased on pre-defined intervals. + * Returns an appropriate label format based on pre-defined intervals. * @param delta The length of the timespan in milliseconds */ export const getLabelFormat = (delta: number): string => { diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/convert_measurements.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/convert_measurements.ts index 4ad9b81b9e660..da97b6400a9a5 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/convert_measurements.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/convert_measurements.ts @@ -8,7 +8,7 @@ const NUM_MICROSECONDS_IN_MILLISECOND = 1000; /** * This simply converts microseconds to milliseconds. People tend to prefer ms to us - * when visualizaing request duration times. + * when visualizing request duration times. */ export const convertMicrosecondsToMilliseconds = (microseconds: number | null): number | null => { if (!microseconds && microseconds !== 0) return null; diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/url_params/__tests__/parse_absolute_date.test.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/url_params/__tests__/parse_absolute_date.test.ts index 691b38bdf9ca2..16888aec21cfe 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/url_params/__tests__/parse_absolute_date.test.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/helper/url_params/__tests__/parse_absolute_date.test.ts @@ -24,7 +24,7 @@ describe('parseAbsoluteDate', () => { it('returns the default value if the parser provides `undefined`', () => { dateMathSpy.mockReturnValue(undefined); - const result = parseAbsoluteDate('this is not a valid datae', 12345); + const result = parseAbsoluteDate('this is not a valid date', 12345); expect(result).toBe(12345); }); }); diff --git a/x-pack/legacy/plugins/uptime/public/lib/helper/url_params/__tests__/parse_autorefresh_interval.test.ts b/x-pack/legacy/plugins/uptime/public/lib/helper/url_params/__tests__/parse_autorefresh_interval.test.ts deleted file mode 100644 index a5c2168378089..0000000000000 --- a/x-pack/legacy/plugins/uptime/public/lib/helper/url_params/__tests__/parse_autorefresh_interval.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { parseUrlInt } from '../parse_url_int'; - -describe('parseUrlInt', () => { - it('parses a number', () => { - const result = parseUrlInt('23', 50); - expect(result).toBe(23); - }); - - it('returns default value for empty string', () => { - const result = parseUrlInt('', 50); - expect(result).toBe(50); - }); - - it('returns default value for non-numeric string', () => { - const result = parseUrlInt('abc', 50); - expect(result).toBe(50); - }); -}); diff --git a/x-pack/legacy/plugins/uptime/public/lib/lib.ts b/x-pack/legacy/plugins/uptime/public/lib/lib.ts index 6b6191441c931..7dd3aa9eed5ce 100644 --- a/x-pack/legacy/plugins/uptime/public/lib/lib.ts +++ b/x-pack/legacy/plugins/uptime/public/lib/lib.ts @@ -5,7 +5,6 @@ */ import { ReactElement } from 'react'; -import { ChromeBreadcrumb } from 'src/core/public'; import { UMBadge } from '../badge'; import { UptimeAppProps } from '../uptime_app'; @@ -13,8 +12,6 @@ export interface UMFrontendLibs { framework: UMFrameworkAdapter; } -export type UMUpdateBreadcrumbs = (breadcrumbs: ChromeBreadcrumb[]) => void; - export type UMUpdateBadge = (badge: UMBadge) => void; export type BootstrapUptimeApp = (props: UptimeAppProps) => ReactElement; diff --git a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx index 683af81239c99..4495be9b24dc1 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/monitor.tsx @@ -8,12 +8,13 @@ import { EuiSpacer } from '@elastic/eui'; import React from 'react'; import { useSelector } from 'react-redux'; import { useTrackPageview } from '../../../../../plugins/observability/public'; -import { MonitorStatusDetails, PingList } from '../components/connected'; import { monitorStatusSelector } from '../state/selectors'; import { PageHeader } from './page_header'; -import { MonitorCharts } from '../components/functional'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; import { useMonitorId, useUptimeTelemetry, UptimePage } from '../hooks'; +import { MonitorCharts } from '../components/monitor'; +import { MonitorStatusDetails } from '../components/monitor'; +import { PingList } from '../components/monitor'; export const MonitorPage: React.FC = () => { const monitorId = useMonitorId(); diff --git a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx index 5b51a208a4c37..adc36efa6f7db 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/overview.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/overview.tsx @@ -8,15 +8,16 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import React, { useEffect } from 'react'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; -import { OverviewPageParsingErrorCallout, StatusPanel } from '../components/functional'; import { useUptimeTelemetry, UptimePage, useGetUrlParams } from '../hooks'; import { stringifyUrlParams } from '../lib/helper/stringify_url_params'; import { useTrackPageview } from '../../../../../plugins/observability/public'; import { DataPublicPluginSetup, IIndexPattern } from '../../../../../../src/plugins/data/public'; -import { EmptyState, FilterGroup, KueryBar, MonitorList } from '../components/connected'; import { useUpdateKueryString } from '../hooks'; import { PageHeader } from './page_header'; import { useBreadcrumbs } from '../hooks/use_breadcrumbs'; +import { MonitorList } from '../components/overview/monitor_list/monitor_list_container'; +import { EmptyState, FilterGroup, KueryBar, ParsingErrorCallout } from '../components/overview'; +import { StatusPanel } from '../components/overview/status_panel'; interface OverviewPageProps { autocomplete: DataPublicPluginSetup['autocomplete']; @@ -75,7 +76,7 @@ export const OverviewPageComponent = ({ autocomplete, indexPattern, setEsKueryFi - {error && } + {error && } diff --git a/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx b/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx index 49e6ddb56602c..b10bc6ba44f8a 100644 --- a/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx +++ b/x-pack/legacy/plugins/uptime/public/pages/page_header.tsx @@ -8,9 +8,9 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Link } from 'react-router-dom'; -import { UptimeDatePicker } from '../components/functional/uptime_date_picker'; +import { UptimeDatePicker } from '../components/common/uptime_date_picker'; import { SETTINGS_ROUTE } from '../../common/constants'; -import { ToggleAlertFlyoutButton } from '../components/connected'; +import { ToggleAlertFlyoutButton } from '../components/overview/alerts/alerts_containers'; interface PageHeaderProps { headingText: string; diff --git a/x-pack/legacy/plugins/uptime/public/routes.tsx b/x-pack/legacy/plugins/uptime/public/routes.tsx index bb0700287dbf1..b5e20ef8a70a9 100644 --- a/x-pack/legacy/plugins/uptime/public/routes.tsx +++ b/x-pack/legacy/plugins/uptime/public/routes.tsx @@ -7,7 +7,7 @@ import React, { FC } from 'react'; import { Route, Switch } from 'react-router-dom'; import { DataPublicPluginSetup } from '../../../../../src/plugins/data/public'; -import { OverviewPage } from './components/connected/pages/overview_container'; +import { OverviewPage } from './components/overview/overview_container'; import { MONITOR_ROUTE, OVERVIEW_ROUTE, SETTINGS_ROUTE } from '../common/constants'; import { MonitorPage, NotFoundPage, SettingsPage } from './pages'; diff --git a/x-pack/legacy/plugins/uptime/public/state/api/monitor.ts b/x-pack/legacy/plugins/uptime/public/state/api/monitor.ts index b36eccca98da9..c3d0a0180cf51 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/monitor.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/monitor.ts @@ -8,7 +8,7 @@ import { BaseParams } from './types'; import { MonitorDetailsType, MonitorLocationsType } from '../../../common/runtime_types'; import { QueryParams } from '../actions/types'; import { apiService } from './utils'; -import { API_URLS } from '../../../common/constants/rest_api'; +import { API_URLS } from '../../../common/constants'; interface ApiRequest { monitorId: string; diff --git a/x-pack/legacy/plugins/uptime/public/state/api/monitor_duration.ts b/x-pack/legacy/plugins/uptime/public/state/api/monitor_duration.ts index daf725119fcf3..91034f1784b15 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/monitor_duration.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/monitor_duration.ts @@ -6,7 +6,7 @@ import { BaseParams } from './types'; import { apiService } from './utils'; -import { API_URLS } from '../../../common/constants/rest_api'; +import { API_URLS } from '../../../common/constants'; export const fetchMonitorDuration = async ({ monitorId, dateStart, dateEnd }: BaseParams) => { const queryParams = { diff --git a/x-pack/legacy/plugins/uptime/public/state/api/overview_filters.ts b/x-pack/legacy/plugins/uptime/public/state/api/overview_filters.ts index 9943bc27f11f0..6330d8a912210 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/overview_filters.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/overview_filters.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { GetOverviewFiltersPayload } from '../actions/overview_filters'; +import { GetOverviewFiltersPayload } from '../actions'; import { OverviewFiltersType } from '../../../common/runtime_types'; import { apiService } from './utils'; -import { API_URLS } from '../../../common/constants/rest_api'; +import { API_URLS } from '../../../common/constants'; export const fetchOverviewFilters = async ({ dateRangeStart, diff --git a/x-pack/legacy/plugins/uptime/public/state/api/ping.ts b/x-pack/legacy/plugins/uptime/public/state/api/ping.ts index bbd3ddf399dcc..6de27879a49f5 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/ping.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/ping.ts @@ -13,7 +13,7 @@ import { HistogramResult, } from '../../../common/runtime_types'; import { apiService } from './utils'; -import { API_URLS } from '../../../common/constants/rest_api'; +import { API_URLS } from '../../../common/constants'; export const fetchPings: APIFn = async ({ dateRange: { from, to }, diff --git a/x-pack/legacy/plugins/uptime/public/state/api/snapshot.ts b/x-pack/legacy/plugins/uptime/public/state/api/snapshot.ts index e663d0241d688..9ee53dd2cbcef 100644 --- a/x-pack/legacy/plugins/uptime/public/state/api/snapshot.ts +++ b/x-pack/legacy/plugins/uptime/public/state/api/snapshot.ts @@ -6,7 +6,7 @@ import { SnapshotType, Snapshot } from '../../../common/runtime_types'; import { apiService } from './utils'; -import { API_URLS } from '../../../common/constants/rest_api'; +import { API_URLS } from '../../../common/constants'; export interface SnapShotQueryParams { dateRangeStart: string; diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts index fa3e377b5ebf4..a98e89a27a711 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/monitor_status.ts @@ -26,7 +26,7 @@ type MonitorStatusPayload = QueryParams & Ping; export const monitorStatusReducer = handleActions( { - [String(getMonitorStatusAction)]: (state, action: Action) => ({ + [String(getMonitorStatusAction)]: state => ({ ...state, loading: true, }), @@ -43,7 +43,7 @@ export const monitorStatusReducer = handleActions) => ({ + [String(getMonitorStatusActionFail)]: state => ({ ...state, loading: false, }), diff --git a/x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts b/x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts index 702d314250521..c533f293fc940 100644 --- a/x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts +++ b/x-pack/legacy/plugins/uptime/public/state/reducers/ui.ts @@ -13,7 +13,7 @@ import { triggerAppRefresh, UiPayload, setAlertFlyoutVisible, -} from '../actions/ui'; +} from '../actions'; export interface UiState { alertFlyoutVisible: boolean; diff --git a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts index dc5df3f93804d..7260c61f44147 100644 --- a/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts +++ b/x-pack/legacy/plugins/uptime/public/state/selectors/index.ts @@ -46,6 +46,16 @@ export const selectPingList = ({ pingList, ui: { lastRefresh } }: AppState) => ( lastRefresh, }); +export const snapshotDataSelector = ({ + snapshot: { count, loading }, + ui: { lastRefresh, esKuery }, +}: AppState) => ({ + count, + lastRefresh, + loading, + esKuery, +}); + const mlCapabilitiesSelector = (state: AppState) => state.ml.mlCapabilities.data; export const hasMLFeatureAvailable = createSelector( diff --git a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx index 556e5b9bf299e..92775a2663863 100644 --- a/x-pack/legacy/plugins/uptime/public/uptime_app.tsx +++ b/x-pack/legacy/plugins/uptime/public/uptime_app.tsx @@ -18,12 +18,14 @@ import { UptimeSettingsContextProvider, UptimeThemeContextProvider, } from './contexts'; -import { CommonlyUsedRange } from './components/functional/uptime_date_picker'; +import { CommonlyUsedRange } from './components/common/uptime_date_picker'; import { store } from './state'; import { setBasePath } from './state/actions'; import { PageRouter } from './routes'; -import { UptimeAlertsFlyoutWrapper } from './components/connected'; -import { UptimeAlertsContextProvider } from './components/functional/alerts'; +import { + UptimeAlertsContextProvider, + UptimeAlertsFlyoutWrapper, +} from './components/overview/alerts'; import { kibanaService } from './state/kibana_service'; export interface UptimeAppColors { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 1170d270e42ac..4e1217ac9e7b5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -16254,7 +16254,6 @@ "xpack.uptime.locationName.helpLinkAnnotation": "場所を追加", "xpack.uptime.ml.durationChart.exploreInMlApp": "ML アプリで探索", "xpack.uptime.ml.enableAnomalyDetectionPanel.anomalyDetectionTitle": "異常検知", - "xpack.uptime.ml.enableAnomalyDetectionPanel.callout.jobExistsDescription.viewJobLinkText": "既存のジョブを表示", "xpack.uptime.ml.enableAnomalyDetectionPanel.createMLJobDescription": "ここでは稼働状況監視の応答時間について異常スコアを計算する機械学習ジョブを作成できます。\n 有効にすると、詳細ページの監視期間チャートに予想範囲が表示され、グラフに異常の注釈が付きます。\n 地理的な地域にわたって遅延が増える期間を特定することもできます。", "xpack.uptime.ml.enableAnomalyDetectionPanel.createNewJobButtonLabel": "新規ジョブを作成", "xpack.uptime.ml.enableAnomalyDetectionPanel.disableAnomalyDetectionTitle": "異常検知を無効にする", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f86e03b6c10e1..bfdcc8b865313 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -16259,7 +16259,6 @@ "xpack.uptime.locationName.helpLinkAnnotation": "添加位置", "xpack.uptime.ml.durationChart.exploreInMlApp": "在 ML 应用中浏览", "xpack.uptime.ml.enableAnomalyDetectionPanel.anomalyDetectionTitle": "异常检测", - "xpack.uptime.ml.enableAnomalyDetectionPanel.callout.jobExistsDescription.viewJobLinkText": "查看现有作业", "xpack.uptime.ml.enableAnomalyDetectionPanel.createMLJobDescription": "在此处可以创建 Machine Learning 作业,以便为运行时间监测计算\n 响应持续时间的异常分数。启用后,详情页面上的监测持续时间图表\n 将显示预期边界并使用异常标注图表。您还可能\n 识别在所有地理区域的延迟增长时段。", "xpack.uptime.ml.enableAnomalyDetectionPanel.createNewJobButtonLabel": "创建新作业", "xpack.uptime.ml.enableAnomalyDetectionPanel.disableAnomalyDetectionTitle": "禁用异常检测", From 9226d4cc94d54b2caaf0b12f98758c0d2df2234b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Mon, 20 Apr 2020 12:43:34 +0100 Subject: [PATCH 02/17] [Telemetry] Use staging if it's not a distributable release (#63875) * [Telemetry] Use staging if it's not a distributable release (instead of 'dev' vs. 'prod' approach) * Rename isProd to isDistributable and useProdKey --- src/plugins/telemetry/server/config.ts | 8 ++++---- .../server/encryption/encrypt.test.ts | 18 +++++++++--------- .../server/encryption/encrypt.ts | 11 +++++++---- .../server/plugin.ts | 10 ++++------ .../server/types.ts | 1 - .../telemetry_collection/get_all_stats.test.ts | 2 -- .../get_stats_with_xpack.test.ts | 1 - 7 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/plugins/telemetry/server/config.ts b/src/plugins/telemetry/server/config.ts index 9621a8b5619b2..99dde0c3b3d96 100644 --- a/src/plugins/telemetry/server/config.ts +++ b/src/plugins/telemetry/server/config.ts @@ -36,8 +36,8 @@ export const configSchema = schema.object({ config: schema.string({ defaultValue: getConfigPath() }), banner: schema.boolean({ defaultValue: true }), url: schema.conditional( - schema.contextRef('dev'), - schema.literal(true), + schema.contextRef('dist'), + schema.literal(false), // Point to staging if it's not a distributable release schema.string({ defaultValue: `https://telemetry-staging.elastic.co/xpack/${ENDPOINT_VERSION}/send`, }), @@ -46,8 +46,8 @@ export const configSchema = schema.object({ }) ), optInStatusUrl: schema.conditional( - schema.contextRef('dev'), - schema.literal(true), + schema.contextRef('dist'), + schema.literal(false), // Point to staging if it's not a distributable release schema.string({ defaultValue: `https://telemetry-staging.elastic.co/opt_in_status/${ENDPOINT_VERSION}/send`, }), diff --git a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts index c04625eb1dd42..6d64268569e06 100644 --- a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts +++ b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.test.ts @@ -22,14 +22,14 @@ import { encryptTelemetry, getKID } from './encrypt'; describe('getKID', () => { it(`returns 'kibana_dev' kid for development`, async () => { - const isProd = false; - const kid = getKID(isProd); + const useProdKey = false; + const kid = getKID(useProdKey); expect(kid).toBe('kibana_dev'); }); it(`returns 'kibana_prod' kid for development`, async () => { - const isProd = true; - const kid = getKID(isProd); + const useProdKey = true; + const kid = getKID(useProdKey); expect(kid).toBe('kibana'); }); }); @@ -41,19 +41,19 @@ describe('encryptTelemetry', () => { it('encrypts payload', async () => { const payload = { some: 'value' }; - await encryptTelemetry(payload, { isProd: true }); + await encryptTelemetry(payload, { useProdKey: true }); expect(createRequestEncryptor).toBeCalledWith(telemetryJWKS); }); - it('uses kibana kid on { isProd: true }', async () => { + it('uses kibana kid on { useProdKey: true }', async () => { const payload = { some: 'value' }; - await encryptTelemetry(payload, { isProd: true }); + await encryptTelemetry(payload, { useProdKey: true }); expect(mockEncrypt).toBeCalledWith('kibana', payload); }); - it('uses kibana_dev kid on { isProd: false }', async () => { + it('uses kibana_dev kid on { useProdKey: false }', async () => { const payload = { some: 'value' }; - await encryptTelemetry(payload, { isProd: false }); + await encryptTelemetry(payload, { useProdKey: false }); expect(mockEncrypt).toBeCalledWith('kibana_dev', payload); }); }); diff --git a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts index 44f053064cfcb..89f34d794f059 100644 --- a/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts +++ b/src/plugins/telemetry_collection_manager/server/encryption/encrypt.ts @@ -20,12 +20,15 @@ import { createRequestEncryptor } from '@elastic/request-crypto'; import { telemetryJWKS } from './telemetry_jwks'; -export function getKID(isProd = false): string { - return isProd ? 'kibana' : 'kibana_dev'; +export function getKID(useProdKey = false): string { + return useProdKey ? 'kibana' : 'kibana_dev'; } -export async function encryptTelemetry(payload: any, { isProd = false } = {}): Promise { - const kid = getKID(isProd); +export async function encryptTelemetry( + payload: any, + { useProdKey = false } = {} +): Promise { + const kid = getKID(useProdKey); const encryptor = await createRequestEncryptor(telemetryJWKS); const clusters = [].concat(payload); return Promise.all(clusters.map((cluster: any) => encryptor.encrypt(kid, cluster))); diff --git a/src/plugins/telemetry_collection_manager/server/plugin.ts b/src/plugins/telemetry_collection_manager/server/plugin.ts index f2f20e215c535..0b57fae83c0fb 100644 --- a/src/plugins/telemetry_collection_manager/server/plugin.ts +++ b/src/plugins/telemetry_collection_manager/server/plugin.ts @@ -50,12 +50,12 @@ export class TelemetryCollectionManagerPlugin private readonly collections: Array> = []; private usageGetterMethodPriority = -1; private usageCollection?: UsageCollectionSetup; - private readonly isDev: boolean; + private readonly isDistributable: boolean; private readonly version: string; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); - this.isDev = initializerContext.env.mode.dev; + this.isDistributable = initializerContext.env.packageInfo.dist; this.version = initializerContext.env.packageInfo.version; } @@ -158,7 +158,7 @@ export class TelemetryCollectionManagerPlugin if (config.unencrypted) { return optInStats; } - return encryptTelemetry(optInStats, { isProd: !this.isDev }); + return encryptTelemetry(optInStats, { useProdKey: this.isDistributable }); } } catch (err) { this.logger.debug(`Failed to collect any opt in stats with registered collections.`); @@ -176,7 +176,6 @@ export class TelemetryCollectionManagerPlugin ) => { const context: StatsCollectionContext = { logger: this.logger.get(collection.title), - isDev: this.isDev, version: this.version, ...collection.customContext, }; @@ -206,7 +205,7 @@ export class TelemetryCollectionManagerPlugin return usageData; } - return encryptTelemetry(usageData, { isProd: !this.isDev }); + return encryptTelemetry(usageData, { useProdKey: this.isDistributable }); } } catch (err) { this.logger.debug( @@ -225,7 +224,6 @@ export class TelemetryCollectionManagerPlugin ): Promise { const context: StatsCollectionContext = { logger: this.logger.get(collection.title), - isDev: this.isDev, version: this.version, ...collection.customContext, }; diff --git a/src/plugins/telemetry_collection_manager/server/types.ts b/src/plugins/telemetry_collection_manager/server/types.ts index e23d6a4c388f4..d3a47694d38a7 100644 --- a/src/plugins/telemetry_collection_manager/server/types.ts +++ b/src/plugins/telemetry_collection_manager/server/types.ts @@ -101,7 +101,6 @@ export interface ESLicense { export interface StatsCollectionContext { logger: Logger; - isDev: boolean; version: string; } diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_all_stats.test.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_all_stats.test.ts index 1a9f2a4da32c2..f0ad6399c6c72 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_all_stats.test.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_all_stats.test.ts @@ -182,7 +182,6 @@ describe('get_all_stats', () => { }, { logger: coreMock.createPluginInitializerContext().logger.get('test'), - isDev: true, version: 'version', maxBucketSize: 1, } @@ -208,7 +207,6 @@ describe('get_all_stats', () => { }, { logger: coreMock.createPluginInitializerContext().logger.get('test'), - isDev: true, version: 'version', maxBucketSize: 1, } diff --git a/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_stats_with_xpack.test.ts b/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_stats_with_xpack.test.ts index f2a9995098e59..5dfe3d3e99a7f 100644 --- a/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_stats_with_xpack.test.ts +++ b/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_stats_with_xpack.test.ts @@ -31,7 +31,6 @@ const kibana = { const getContext = () => ({ version: '8675309-snapshot', - isDev: true, logger: coreMock.createPluginInitializerContext().logger.get('test'), }); From 21dda535ebfa31b794cc0a1ba608570bcd6a2256 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Mon, 20 Apr 2020 14:08:04 +0200 Subject: [PATCH 03/17] =?UTF-8?q?Upgrade=20`papaparse`=20dependency=20(`4.?= =?UTF-8?q?6.3`=20=E2=86=92=20`5.2.0`).=20(#63879)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- x-pack/package.json | 4 ++-- yarn.lock | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/x-pack/package.json b/x-pack/package.json index a4fdb17f52fe5..3c6146b491f60 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -85,7 +85,7 @@ "@types/node-fetch": "^2.5.0", "@types/nodemailer": "^6.2.1", "@types/object-hash": "^1.3.0", - "@types/papaparse": "^4.5.11", + "@types/papaparse": "^5.0.3", "@types/pngjs": "^3.3.2", "@types/prop-types": "^15.5.3", "@types/proper-lockfile": "^3.0.1", @@ -290,7 +290,7 @@ "oboe": "^2.1.4", "oppsy": "^2.0.0", "p-retry": "^4.2.0", - "papaparse": "^4.6.3", + "papaparse": "^5.2.0", "pdfmake": "^0.1.63", "pluralize": "3.1.0", "pngjs": "3.4.0", diff --git a/yarn.lock b/yarn.lock index 45540cd2675b7..b47befbf9057b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4477,10 +4477,10 @@ dependencies: "@types/node" "*" -"@types/papaparse@^4.5.11": - version "4.5.11" - resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-4.5.11.tgz#dcd4f64da55f768c2e2cf92ccac1973c67a73890" - integrity sha512-zOw6K7YyA/NuZ2yZ8lzZFe2U3fn+vFfcRfiQp4ZJHG6y8WYWy2SYFbq6mp4yUgpIruJHBjKZtgyE0vvCoWEq+A== +"@types/papaparse@^5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-5.0.3.tgz#7cedc1ebc9484819af8306a8b42f9f08ca9bdb44" + integrity sha512-SgWGWnBGxl6XgjKDM2eoDg163ZFQtH6m6C2aOuaAf1T2gUB3rjaiPDDARbY9WlacRgZqieRG9imAfJaJ+5ouDA== dependencies: "@types/node" "*" @@ -22585,10 +22585,10 @@ pako@~1.0.5: resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== -papaparse@^4.6.3: - version "4.6.3" - resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-4.6.3.tgz#742e5eaaa97fa6c7e1358d2934d8f18f44aee781" - integrity sha512-LRq7BrHC2kHPBYSD50aKuw/B/dGcg29omyJbKWY3KsYUZU69RKwaBHu13jGmCYBtOc4odsLCrFyk6imfyNubJQ== +papaparse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.2.0.tgz#97976a1b135c46612773029153dc64995caa3b7b" + integrity sha512-ylq1wgUSnagU+MKQtNeVqrPhZuMYBvOSL00DHycFTCxownF95gpLAk1HiHdUW77N8yxRq1qHXLdlIPyBSG9NSA== parallel-transform@^1.1.0: version "1.1.0" From 8f7bb05169d148751fc66e235dfe77ab0315dee0 Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Mon, 20 Apr 2020 15:04:14 +0200 Subject: [PATCH 04/17] [Discuss] Remove expressions plugin's dependency on inspector plugin (#63841) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 💡 use inspector service in visualizations to open it * refactor: 💡 remove expressions plugin dependency on inspector * test: 💍 fix Jest mock * fix: 🐛 remove Inspectore from Expressions plugin dependency inf * docs: ✏️ add JSDocs for createStartServicesGetter() method * test: 💍 fix TypeScript errors in expressions mocks --- src/plugins/expressions/kibana.json | 3 +- src/plugins/expressions/public/loader.ts | 16 ++----- src/plugins/expressions/public/mocks.tsx | 3 -- src/plugins/expressions/public/plugin.ts | 9 +--- .../public/react_expression_renderer.tsx | 3 +- src/plugins/expressions/public/render.ts | 3 +- src/plugins/expressions/public/services.ts | 3 -- .../core/create_start_service_getter.ts | 42 +++++++++++++++++++ src/plugins/visualizations/kibana.json | 2 +- .../create_vis_embeddable_from_object.ts | 4 +- .../public/embeddable/visualize_embeddable.ts | 17 ++++++-- .../visualize_embeddable_factory.tsx | 13 ++++-- src/plugins/visualizations/public/mocks.ts | 5 ++- src/plugins/visualizations/public/plugin.ts | 34 ++++++++++----- 14 files changed, 107 insertions(+), 50 deletions(-) diff --git a/src/plugins/expressions/kibana.json b/src/plugins/expressions/kibana.json index cba693dd4bc20..5d2112103e94d 100644 --- a/src/plugins/expressions/kibana.json +++ b/src/plugins/expressions/kibana.json @@ -4,7 +4,6 @@ "server": true, "ui": true, "requiredPlugins": [ - "bfetch", - "inspector" + "bfetch" ] } diff --git a/src/plugins/expressions/public/loader.ts b/src/plugins/expressions/public/loader.ts index fbe2f37c648d6..418ff6fdf8614 100644 --- a/src/plugins/expressions/public/loader.ts +++ b/src/plugins/expressions/public/loader.ts @@ -19,13 +19,14 @@ import { BehaviorSubject, Observable, Subject } from 'rxjs'; import { filter, map } from 'rxjs/operators'; -import { Adapters, InspectorSession } from '../../inspector/public'; -import { ExpressionRenderHandler } from './render'; +import { Adapters } from '../../inspector/public'; import { IExpressionLoaderParams } from './types'; import { ExpressionAstExpression } from '../common'; -import { getInspector, getExpressionsService } from './services'; import { ExecutionContract } from '../common/execution/execution_contract'; +import { ExpressionRenderHandler } from './render'; +import { getExpressionsService } from './services'; + type Data = any; export class ExpressionLoader { @@ -120,15 +121,6 @@ export class ExpressionLoader { return this.renderHandler.getElement(); } - openInspector(title: string): InspectorSession | undefined { - const inspector = this.inspect(); - if (inspector) { - return getInspector().open(inspector, { - title, - }); - } - } - inspect(): Adapters | undefined { return this.execution ? (this.execution.inspect() as Adapters) : undefined; } diff --git a/src/plugins/expressions/public/mocks.tsx b/src/plugins/expressions/public/mocks.tsx index cb7089f814643..b8f2f693e9c77 100644 --- a/src/plugins/expressions/public/mocks.tsx +++ b/src/plugins/expressions/public/mocks.tsx @@ -22,7 +22,6 @@ import { ExpressionsSetup, ExpressionsStart, plugin as pluginInitializer } from /* eslint-disable */ import { coreMock } from '../../../core/public/mocks'; -import { inspectorPluginMock } from '../../inspector/public/mocks'; import { bfetchPluginMock } from '../../bfetch/public/mocks'; /* eslint-enable */ @@ -89,7 +88,6 @@ const createPlugin = async () => { const plugin = pluginInitializer(pluginInitializerContext); const setup = await plugin.setup(coreSetup, { bfetch: bfetchPluginMock.createSetupContract(), - inspector: inspectorPluginMock.createSetupContract(), }); return { @@ -101,7 +99,6 @@ const createPlugin = async () => { doStart: async () => await plugin.start(coreStart, { bfetch: bfetchPluginMock.createStartContract(), - inspector: inspectorPluginMock.createStartContract(), }), }; }; diff --git a/src/plugins/expressions/public/plugin.ts b/src/plugins/expressions/public/plugin.ts index 7c0de271b7706..720c3b701d504 100644 --- a/src/plugins/expressions/public/plugin.ts +++ b/src/plugins/expressions/public/plugin.ts @@ -29,11 +29,9 @@ import { ExpressionsServiceStart, ExecutionContext, } from '../common'; -import { Setup as InspectorSetup, Start as InspectorStart } from '../../inspector/public'; import { BfetchPublicSetup, BfetchPublicStart } from '../../bfetch/public'; import { setCoreStart, - setInspector, setInterpreter, setRenderersRegistry, setNotifications, @@ -45,12 +43,10 @@ import { render, ExpressionRenderHandler } from './render'; export interface ExpressionsSetupDeps { bfetch: BfetchPublicSetup; - inspector: InspectorSetup; } export interface ExpressionsStartDeps { bfetch: BfetchPublicStart; - inspector: InspectorStart; } export interface ExpressionsSetup extends ExpressionsServiceSetup { @@ -120,7 +116,7 @@ export class ExpressionsPublicPlugin }); } - public setup(core: CoreSetup, { inspector, bfetch }: ExpressionsSetupDeps): ExpressionsSetup { + public setup(core: CoreSetup, { bfetch }: ExpressionsSetupDeps): ExpressionsSetup { this.configureExecutor(core); const { expressions } = this; @@ -180,9 +176,8 @@ export class ExpressionsPublicPlugin return Object.freeze(setup); } - public start(core: CoreStart, { inspector, bfetch }: ExpressionsStartDeps): ExpressionsStart { + public start(core: CoreStart, { bfetch }: ExpressionsStartDeps): ExpressionsStart { setCoreStart(core); - setInspector(inspector); setNotifications(core.notifications); const { expressions } = this; diff --git a/src/plugins/expressions/public/react_expression_renderer.tsx b/src/plugins/expressions/public/react_expression_renderer.tsx index 242a49c6d6639..2c99f173c9f33 100644 --- a/src/plugins/expressions/public/react_expression_renderer.tsx +++ b/src/plugins/expressions/public/react_expression_renderer.tsx @@ -17,8 +17,7 @@ * under the License. */ -import { useRef, useEffect, useState, useLayoutEffect } from 'react'; -import React from 'react'; +import React, { useRef, useEffect, useState, useLayoutEffect } from 'react'; import classNames from 'classnames'; import { Subscription } from 'rxjs'; import { filter } from 'rxjs/operators'; diff --git a/src/plugins/expressions/public/render.ts b/src/plugins/expressions/public/render.ts index ad4d16bcd1323..4aaf0da60fc60 100644 --- a/src/plugins/expressions/public/render.ts +++ b/src/plugins/expressions/public/render.ts @@ -21,10 +21,11 @@ import * as Rx from 'rxjs'; import { Observable } from 'rxjs'; import { filter } from 'rxjs/operators'; import { RenderError, RenderErrorHandlerFnType, IExpressionLoaderParams } from './types'; -import { getRenderersRegistry } from './services'; import { renderErrorHandler as defaultRenderErrorHandler } from './render_error_handler'; import { IInterpreterRenderHandlers, ExpressionAstExpression } from '../common'; +import { getRenderersRegistry } from './services'; + export type IExpressionRendererExtraHandlers = Record; export interface ExpressionRenderHandlerParams { diff --git a/src/plugins/expressions/public/services.ts b/src/plugins/expressions/public/services.ts index a203e87414571..016456c956666 100644 --- a/src/plugins/expressions/public/services.ts +++ b/src/plugins/expressions/public/services.ts @@ -20,14 +20,11 @@ import { NotificationsStart } from 'kibana/public'; import { createKibanaUtilsCore, createGetterSetter } from '../../kibana_utils/public'; import { ExpressionInterpreter } from './types'; -import { Start as IInspector } from '../../inspector/public'; import { ExpressionsSetup } from './plugin'; import { ExpressionsService } from '../common'; export const { getCoreStart, setCoreStart } = createKibanaUtilsCore(); -export const [getInspector, setInspector] = createGetterSetter('Inspector'); - export const [getInterpreter, setInterpreter] = createGetterSetter( 'Interpreter' ); diff --git a/src/plugins/kibana_utils/public/core/create_start_service_getter.ts b/src/plugins/kibana_utils/public/core/create_start_service_getter.ts index e507d1ae778e5..5e385eb5ed473 100644 --- a/src/plugins/kibana_utils/public/core/create_start_service_getter.ts +++ b/src/plugins/kibana_utils/public/core/create_start_service_getter.ts @@ -30,6 +30,48 @@ export type StartServicesGetter = () = OwnContract >; +/** + * Use this utility to create a synchronous *start* service getter in *setup* + * life-cycle of your plugin. + * + * Below is a usage example in a Kibana plugin. + * + * ```ts + * export interface MyPluginStartDeps { + * data: DataPublicPluginStart; + * expressions: ExpressionsStart; + * inspector: InspectorStart; + * uiActions: UiActionsStart; + * } + * + * class MyPlugin implements Plugin { + * setup(core: CoreSetup, plugins) { + * const start = createStartServicesGetter(core.getStartServices); + * plugins.expressions.registerFunction(myExpressionFunction(start)); + * } + * + * start(core, plugins: MyPluginStartDeps) { + * + * } + * } + * ``` + * + * In `myExpressionFunction` you can make sure you are picking only the dependencies + * your function needs using the `Pick` type. + * + * ```ts + * const myExpressionFunction = + * (start: StartServicesGetter>) => { + * + * start().plugins.indexPatterns.something(123); + * } + * ``` + * + * @param accessor Asynchronous start service accessor provided by platform. + * @returns Returns a function which synchronously returns *start* core services + * and plugin contracts. If you call this function before the *start* life-cycle + * has started it will throw. + */ export const createStartServicesGetter = ( accessor: StartServicesAccessor ): StartServicesGetter => { diff --git a/src/plugins/visualizations/kibana.json b/src/plugins/visualizations/kibana.json index cd22b1375ae1b..f3f9cbd8341ec 100644 --- a/src/plugins/visualizations/kibana.json +++ b/src/plugins/visualizations/kibana.json @@ -3,5 +3,5 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection"] + "requiredPlugins": ["data", "expressions", "uiActions", "embeddable", "usageCollection", "inspector"] } diff --git a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts index bf2d174f594b2..8e51bd4ac5d4f 100644 --- a/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts +++ b/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts @@ -28,8 +28,9 @@ import { getTimeFilter, getCapabilities, } from '../services'; +import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; -export const createVisEmbeddableFromObject = async ( +export const createVisEmbeddableFromObject = (deps: VisualizeEmbeddableFactoryDeps) => async ( vis: Vis, input: Partial & { id: string }, parent?: IContainer @@ -58,6 +59,7 @@ export const createVisEmbeddableFromObject = async ( indexPatterns, editUrl, editable, + deps, }, input, parent diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index e64d200251797..ffb028ff131b3 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -42,6 +42,7 @@ import { buildPipeline } from '../legacy/build_pipeline'; import { Vis } from '../vis'; import { getExpressions, getUiActions } from '../services'; import { VIS_EVENT_TO_TRIGGER } from './events'; +import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; const getKeys = (o: T): Array => Object.keys(o) as Array; @@ -50,6 +51,7 @@ export interface VisualizeEmbeddableConfiguration { indexPatterns?: IIndexPattern[]; editUrl: string; editable: boolean; + deps: VisualizeEmbeddableFactoryDeps; } export interface VisualizeInput extends EmbeddableInput { @@ -84,10 +86,11 @@ export class VisualizeEmbeddable extends Embeddable { - if (this.handler) { - return this.handler.openInspector(this.getTitle() || ''); - } + if (!this.handler) return; + + const adapters = this.handler.inspect(); + if (!adapters) return; + + this.deps.start().plugins.inspector.open(adapters, { + title: this.getTitle() || '', + }); }; /** diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 4b7d01ae3b246..6ab1c98645988 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -25,7 +25,7 @@ import { EmbeddableOutput, ErrorEmbeddable, IContainer, -} from '../../../../plugins/embeddable/public'; +} from '../../../embeddable/public'; import { DisabledLabEmbeddable } from './disabled_lab_embeddable'; import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable'; import { VISUALIZE_EMBEDDABLE_TYPE } from './constants'; @@ -39,11 +39,17 @@ import { import { showNewVisModal } from '../wizard'; import { convertToSerializedVis } from '../saved_visualizations/_saved_vis'; import { createVisEmbeddableFromObject } from './create_vis_embeddable_from_object'; +import { StartServicesGetter } from '../../../kibana_utils/public'; +import { VisualizationsStartDeps } from '../plugin'; interface VisualizationAttributes extends SavedObjectAttributes { visState: string; } +export interface VisualizeEmbeddableFactoryDeps { + start: StartServicesGetter>; +} + export class VisualizeEmbeddableFactory implements EmbeddableFactoryDefinition< @@ -79,7 +85,8 @@ export class VisualizeEmbeddableFactory return visType.stage !== 'experimental'; }, }; - constructor() {} + + constructor(private readonly deps: VisualizeEmbeddableFactoryDeps) {} public async isEditable() { return getCapabilities().visualize.save as boolean; @@ -101,7 +108,7 @@ export class VisualizeEmbeddableFactory try { const savedObject = await savedVisualizations.get(savedObjectId); const vis = new Vis(savedObject.visState.type, await convertToSerializedVis(savedObject)); - return createVisEmbeddableFromObject(vis, input, parent); + return createVisEmbeddableFromObject(this.deps)(vis, input, parent); } catch (e) { console.error(e); // eslint-disable-line no-console return new ErrorEmbeddable(e, input, parent); diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index 2aa346423297a..d6eeffdb01459 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -26,6 +26,7 @@ import { expressionsPluginMock } from '../../../plugins/expressions/public/mocks import { dataPluginMock } from '../../../plugins/data/public/mocks'; import { usageCollectionPluginMock } from '../../../plugins/usage_collection/public/mocks'; import { uiActionsPluginMock } from '../../../plugins/ui_actions/public/mocks'; +import { inspectorPluginMock } from '../../../plugins/inspector/public/mocks'; const createSetupContract = (): VisualizationsSetup => ({ createBaseVisualization: jest.fn(), @@ -53,14 +54,16 @@ const createInstance = async () => { const setup = plugin.setup(coreMock.createSetup(), { data: dataPluginMock.createSetupContract(), - expressions: expressionsPluginMock.createSetupContract(), embeddable: embeddablePluginMock.createSetupContract(), + expressions: expressionsPluginMock.createSetupContract(), + inspector: inspectorPluginMock.createSetupContract(), usageCollection: usageCollectionPluginMock.createSetupContract(), }); const doStart = () => plugin.start(coreMock.createStart(), { data: dataPluginMock.createStartContract(), expressions: expressionsPluginMock.createStartContract(), + inspector: inspectorPluginMock.createStartContract(), uiActions: uiActionsPluginMock.createStartContract(), }); diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 8fcb84b19a9be..b3e8c9b5b61b3 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -43,18 +43,23 @@ import { VisualizeEmbeddableFactory, createVisEmbeddableFromObject, } from './embeddable'; -import { ExpressionsSetup, ExpressionsStart } from '../../../plugins/expressions/public'; -import { EmbeddableSetup } from '../../../plugins/embeddable/public'; +import { ExpressionsSetup, ExpressionsStart } from '../../expressions/public'; +import { EmbeddableSetup } from '../../embeddable/public'; import { visualization as visualizationFunction } from './expressions/visualization_function'; import { visualization as visualizationRenderer } from './expressions/visualization_renderer'; import { range as rangeExpressionFunction } from './expression_functions/range'; import { visDimension as visDimensionExpressionFunction } from './expression_functions/vis_dimension'; import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../plugins/data/public'; -import { UsageCollectionSetup } from '../../../plugins/usage_collection/public'; +import { + Setup as InspectorSetup, + Start as InspectorStart, +} from '../../../plugins/inspector/public'; +import { UsageCollectionSetup } from '../../usage_collection/public'; +import { createStartServicesGetter, StartServicesGetter } from '../../kibana_utils/public'; import { createSavedVisLoader, SavedVisualizationsLoader } from './saved_visualizations'; import { SerializedVis, Vis } from './vis'; import { showNewVisModal } from './wizard'; -import { UiActionsStart } from '../../../plugins/ui_actions/public'; +import { UiActionsStart } from '../../ui_actions/public'; import { convertFromSerializedVis, convertToSerializedVis, @@ -74,19 +79,21 @@ export interface VisualizationsStart extends TypesStart { convertToSerializedVis: typeof convertToSerializedVis; convertFromSerializedVis: typeof convertFromSerializedVis; showNewVisModal: typeof showNewVisModal; - __LEGACY: { createVisEmbeddableFromObject: typeof createVisEmbeddableFromObject }; + __LEGACY: { createVisEmbeddableFromObject: ReturnType }; } export interface VisualizationsSetupDeps { - expressions: ExpressionsSetup; + data: DataPublicPluginSetup; embeddable: EmbeddableSetup; + expressions: ExpressionsSetup; + inspector: InspectorSetup; usageCollection: UsageCollectionSetup; - data: DataPublicPluginSetup; } export interface VisualizationsStartDeps { data: DataPublicPluginStart; expressions: ExpressionsStart; + inspector: InspectorStart; uiActions: UiActionsStart; } @@ -107,13 +114,16 @@ export class VisualizationsPlugin VisualizationsStartDeps > { private readonly types: TypesService = new TypesService(); + private getStartServicesOrDie?: StartServicesGetter; constructor(initializerContext: PluginInitializerContext) {} public setup( - core: CoreSetup, + core: CoreSetup, { expressions, embeddable, usageCollection, data }: VisualizationsSetupDeps ): VisualizationsSetup { + const start = (this.getStartServicesOrDie = createStartServicesGetter(core.getStartServices)); + setUISettings(core.uiSettings); setUsageCollector(usageCollection); @@ -122,7 +132,7 @@ export class VisualizationsPlugin expressions.registerFunction(rangeExpressionFunction); expressions.registerFunction(visDimensionExpressionFunction); - const embeddableFactory = new VisualizeEmbeddableFactory(); + const embeddableFactory = new VisualizeEmbeddableFactory({ start }); embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory); return { @@ -171,7 +181,11 @@ export class VisualizationsPlugin convertToSerializedVis, convertFromSerializedVis, savedVisualizationsLoader, - __LEGACY: { createVisEmbeddableFromObject }, + __LEGACY: { + createVisEmbeddableFromObject: createVisEmbeddableFromObject({ + start: this.getStartServicesOrDie!, + }), + }, }; } From 878cc8b14e5c18ff78641d8ac8d762d2a527b296 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 20 Apr 2020 16:26:48 +0200 Subject: [PATCH 05/17] Add redirect function to kibana_legacy legacy application service (#63702) --- .../core_plugins/kibana/public/kibana.js | 5 +- .../local_application_service.ts | 25 ++++++-- .../new_platform/new_platform.karma_mock.js | 2 + src/plugins/kibana_legacy/public/mocks.ts | 2 + src/plugins/kibana_legacy/public/plugin.ts | 60 +++++++++++++++++-- 5 files changed, 82 insertions(+), 12 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/kibana.js b/src/legacy/core_plugins/kibana/public/kibana.js index 20c46765dcb30..ea0d5ad3790b1 100644 --- a/src/legacy/core_plugins/kibana/public/kibana.js +++ b/src/legacy/core_plugins/kibana/public/kibana.js @@ -49,8 +49,9 @@ import { showAppRedirectNotification } from '../../../../plugins/kibana_legacy/p import 'leaflet'; import { localApplicationService } from './local_application_service'; -npSetup.plugins.kibanaLegacy.forwardApp('doc', 'discover', { keepPrefix: true }); -npSetup.plugins.kibanaLegacy.forwardApp('context', 'discover', { keepPrefix: true }); +npSetup.plugins.kibanaLegacy.registerLegacyAppAlias('doc', 'discover', { keepPrefix: true }); +npSetup.plugins.kibanaLegacy.registerLegacyAppAlias('context', 'discover', { keepPrefix: true }); + localApplicationService.attachToAngular(routes); routes.enable(); diff --git a/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts b/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts index 14564cfd9ee78..f38c410e6832f 100644 --- a/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts +++ b/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts @@ -98,14 +98,29 @@ export class LocalApplicationService { } }); - npStart.plugins.kibanaLegacy.getForwards().forEach(({ legacyAppId, newAppId, keepPrefix }) => { - angularRouteManager.when(matchAllWithPrefix(legacyAppId), { - resolveRedirectTo: ($location: ILocationService) => { - const url = $location.url(); - return `/${newAppId}${keepPrefix ? url : url.replace(legacyAppId, '')}`; + npStart.plugins.kibanaLegacy.getForwards().forEach(forwardDefinition => { + angularRouteManager.when(matchAllWithPrefix(forwardDefinition.legacyAppId), { + outerAngularWrapperRoute: true, + reloadOnSearch: false, + reloadOnUrl: false, + template: '', + controller($location: ILocationService) { + const newPath = forwardDefinition.rewritePath($location.url()); + npStart.core.application.navigateToApp(forwardDefinition.newAppId, { path: newPath }); }, }); }); + + npStart.plugins.kibanaLegacy + .getLegacyAppAliases() + .forEach(({ legacyAppId, newAppId, keepPrefix }) => { + angularRouteManager.when(matchAllWithPrefix(legacyAppId), { + resolveRedirectTo: ($location: ILocationService) => { + const url = $location.url(); + return `/${newAppId}${keepPrefix ? url : url.replace(legacyAppId, '')}`; + }, + }); + }); } } diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index f577a29ce90b9..f14f26613ef01 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -242,6 +242,7 @@ export const npSetup = { }, kibanaLegacy: { registerLegacyApp: () => {}, + registerLegacyAppAlias: () => {}, forwardApp: () => {}, config: { defaultAppId: 'home', @@ -362,6 +363,7 @@ export const npStart = { kibanaLegacy: { getApps: () => [], getForwards: () => [], + getLegacyAppAliases: () => [], config: { defaultAppId: 'home', }, diff --git a/src/plugins/kibana_legacy/public/mocks.ts b/src/plugins/kibana_legacy/public/mocks.ts index 8e9a05b186191..2fdd0d8b4be59 100644 --- a/src/plugins/kibana_legacy/public/mocks.ts +++ b/src/plugins/kibana_legacy/public/mocks.ts @@ -25,6 +25,7 @@ export type Start = jest.Mocked>; const createSetupContract = (): Setup => ({ forwardApp: jest.fn(), + registerLegacyAppAlias: jest.fn(), registerLegacyApp: jest.fn(), config: { defaultAppId: 'home', @@ -37,6 +38,7 @@ const createSetupContract = (): Setup => ({ const createStartContract = (): Start => ({ getApps: jest.fn(), + getLegacyAppAliases: jest.fn(), getForwards: jest.fn(), config: { defaultAppId: 'home', diff --git a/src/plugins/kibana_legacy/public/plugin.ts b/src/plugins/kibana_legacy/public/plugin.ts index 2ad620f355848..831fc3f0d4a71 100644 --- a/src/plugins/kibana_legacy/public/plugin.ts +++ b/src/plugins/kibana_legacy/public/plugin.ts @@ -28,12 +28,18 @@ import { Observable } from 'rxjs'; import { ConfigSchema } from '../config'; import { getDashboardConfig } from './dashboard_config'; -interface ForwardDefinition { +interface LegacyAppAliasDefinition { legacyAppId: string; newAppId: string; keepPrefix: boolean; } +interface ForwardDefinition { + legacyAppId: string; + newAppId: string; + rewritePath: (legacyPath: string) => string; +} + export type AngularRenderedAppUpdater = ( app: AppBase ) => Partial | undefined; @@ -54,7 +60,8 @@ export interface AngularRenderedApp extends App { export class KibanaLegacyPlugin { private apps: AngularRenderedApp[] = []; - private forwards: ForwardDefinition[] = []; + private legacyAppAliases: LegacyAppAliasDefinition[] = []; + private forwardDefinitions: ForwardDefinition[] = []; constructor(private readonly initializerContext: PluginInitializerContext) {} @@ -94,17 +101,55 @@ export class KibanaLegacyPlugin { * renaming or nesting plugins. For route changes after the prefix, please * use the routing mechanism of your app. * + * This method just redirects URLs within the legacy `kibana` app. + * * @param legacyAppId The name of the old app to forward URLs from * @param newAppId The name of the new app that handles the URLs now * @param options Whether the prefix of the old app is kept to nest the legacy * path into the new path */ - forwardApp: ( + registerLegacyAppAlias: ( legacyAppId: string, newAppId: string, options: { keepPrefix: boolean } = { keepPrefix: false } ) => { - this.forwards.push({ legacyAppId, newAppId, ...options }); + this.legacyAppAliases.push({ legacyAppId, newAppId, ...options }); + }, + + /** + * Forwards URLs within the legacy `kibana` app to a new platform application. + * + * @param legacyAppId The name of the old app to forward URLs from + * @param newAppId The name of the new app that handles the URLs now + * @param rewritePath Function to rewrite the legacy sub path of the app to the new path in the core app + * path into the new path + * + * Example usage: + * ``` + * kibanaLegacy.forwardApp( + * 'old', + * 'new', + * path => { + * const [, id] = /old/item\/(.*)$/.exec(path) || []; + * if (!id) { + * return '#/home'; + * } + * return '#/items/${id}'; + * } + * ); + * ``` + * This will cause the following redirects: + * + * * app/kibana#/old/ -> app/new#/home + * * app/kibana#/old/item/123 -> app/new#/items/123 + * + */ + forwardApp: ( + legacyAppId: string, + newAppId: string, + rewritePath: (legacyPath: string) => string + ) => { + this.forwardDefinitions.push({ legacyAppId, newAppId, rewritePath }); }, /** @@ -132,7 +177,12 @@ export class KibanaLegacyPlugin { * @deprecated * Just exported for wiring up with legacy platform, should not be used. */ - getForwards: () => this.forwards, + getLegacyAppAliases: () => this.legacyAppAliases, + /** + * @deprecated + * Just exported for wiring up with legacy platform, should not be used. + */ + getForwards: () => this.forwardDefinitions, config: this.initializerContext.config.get(), dashboardConfig: getDashboardConfig(!application.capabilities.dashboard.showWriteControls), }; From 32c6fd777f1b879ce4e03758af28f22800a2fb18 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 20 Apr 2020 08:21:11 -0700 Subject: [PATCH 06/17] Revert "[platform] serve plugins from /bundles/plugin:${id}" This reverts commit d538929ed96ff61df0d0d99b4065f881aee4ebcd. --- src/core/public/plugins/plugin_loader.test.ts | 12 ++++++------ src/core/public/plugins/plugin_loader.ts | 2 +- src/legacy/ui/ui_render/bootstrap/template.js.hbs | 8 ++++---- src/optimize/bundles_route/bundles_route.js | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/core/public/plugins/plugin_loader.test.ts b/src/core/public/plugins/plugin_loader.test.ts index 18cc2d7a6f182..b4e2c3095f14a 100644 --- a/src/core/public/plugins/plugin_loader.test.ts +++ b/src/core/public/plugins/plugin_loader.test.ts @@ -62,7 +62,7 @@ test('`loadPluginBundles` creates a script tag and loads initializer', async () const fakeScriptTag = createdScriptTags[0]; expect(fakeScriptTag.setAttribute).toHaveBeenCalledWith( 'src', - '/bundles/plugin:plugin-a/plugin-a.plugin.js' + '/bundles/plugin/plugin-a/plugin-a.plugin.js' ); expect(fakeScriptTag.setAttribute).toHaveBeenCalledWith('id', 'kbn-plugin-plugin-a'); expect(fakeScriptTag.onload).toBeInstanceOf(Function); @@ -85,7 +85,7 @@ test('`loadPluginBundles` includes the basePath', async () => { const fakeScriptTag = createdScriptTags[0]; expect(fakeScriptTag.setAttribute).toHaveBeenCalledWith( 'src', - '/mybasepath/bundles/plugin:plugin-a/plugin-a.plugin.js' + '/mybasepath/bundles/plugin/plugin-a/plugin-a.plugin.js' ); }); @@ -96,7 +96,7 @@ test('`loadPluginBundles` rejects if script.onerror is called', async () => { fakeScriptTag1.onerror(new Error('Whoa there!')); await expect(loadPromise).rejects.toThrowErrorMatchingInlineSnapshot( - `"Failed to load \\"plugin-a\\" bundle (/bundles/plugin:plugin-a/plugin-a.plugin.js)"` + `"Failed to load \\"plugin-a\\" bundle (/bundles/plugin/plugin-a/plugin-a.plugin.js)"` ); }); @@ -105,7 +105,7 @@ test('`loadPluginBundles` rejects if timeout is reached', async () => { // Override the timeout to 1 ms for testi. loadPluginBundle(addBasePath, 'plugin-a', { timeoutMs: 1 }) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Timeout reached when loading \\"plugin-a\\" bundle (/bundles/plugin:plugin-a/plugin-a.plugin.js)"` + `"Timeout reached when loading \\"plugin-a\\" bundle (/bundles/plugin/plugin-a/plugin-a.plugin.js)"` ); }); @@ -115,11 +115,11 @@ test('`loadPluginBundles` rejects if bundle does attach an initializer to window const fakeScriptTag1 = createdScriptTags[0]; // Setup a fake initializer as if a plugin bundle had actually been loaded. - coreWindow.__kbnBundles__['plugin:plugin-a'] = undefined; + coreWindow.__kbnBundles__['plugin/plugin-a'] = undefined; // Call the onload callback fakeScriptTag1.onload(); await expect(loadPromise).rejects.toThrowErrorMatchingInlineSnapshot( - `"Definition of plugin \\"plugin-a\\" should be a function (/bundles/plugin:plugin-a/plugin-a.plugin.js)."` + `"Definition of plugin \\"plugin-a\\" should be a function (/bundles/plugin/plugin-a/plugin-a.plugin.js)."` ); }); diff --git a/src/core/public/plugins/plugin_loader.ts b/src/core/public/plugins/plugin_loader.ts index 9b35588dfe726..bf7711055e97b 100644 --- a/src/core/public/plugins/plugin_loader.ts +++ b/src/core/public/plugins/plugin_loader.ts @@ -93,7 +93,7 @@ export const loadPluginBundle: LoadPluginBundle = < const script = document.createElement('script'); // Assumes that all plugin bundles get put into the bundles/plugins subdirectory - const bundlePath = addBasePath(`/bundles/plugin:${pluginName}/${pluginName}.plugin.js`); + const bundlePath = addBasePath(`/bundles/plugin/${pluginName}/${pluginName}.plugin.js`); script.setAttribute('src', bundlePath); script.setAttribute('id', `kbn-plugin-${pluginName}`); script.setAttribute('async', ''); diff --git a/src/legacy/ui/ui_render/bootstrap/template.js.hbs b/src/legacy/ui/ui_render/bootstrap/template.js.hbs index 4557d911620a2..1093153edbbf7 100644 --- a/src/legacy/ui/ui_render/bootstrap/template.js.hbs +++ b/src/legacy/ui/ui_render/bootstrap/template.js.hbs @@ -78,10 +78,10 @@ if (window.__kbnStrictCsp__ && window.__kbnCspNotEnforced__) { '{{this}}', {{/each}} '{{regularBundlePath}}/commons.bundle.js', - {{!-- '{{regularBundlePath}}/plugin:data/data.plugin.js', --}} - '{{regularBundlePath}}/plugin:kibanaUtils/kibanaUtils.plugin.js', - '{{regularBundlePath}}/plugin:esUiShared/esUiShared.plugin.js', - '{{regularBundlePath}}/plugin:kibanaReact/kibanaReact.plugin.js' + {{!-- '{{regularBundlePath}}/plugin/data/data.plugin.js', --}} + '{{regularBundlePath}}/plugin/kibanaUtils/kibanaUtils.plugin.js', + '{{regularBundlePath}}/plugin/esUiShared/esUiShared.plugin.js', + '{{regularBundlePath}}/plugin/kibanaReact/kibanaReact.plugin.js' ], function () { load([ '{{regularBundlePath}}/{{appId}}.bundle.js', diff --git a/src/optimize/bundles_route/bundles_route.js b/src/optimize/bundles_route/bundles_route.js index f4e3108f80a3b..0c2e98b5acd63 100644 --- a/src/optimize/bundles_route/bundles_route.js +++ b/src/optimize/bundles_route/bundles_route.js @@ -79,8 +79,8 @@ export function createBundlesRoute({ ), ...npUiPluginPublicDirs.map(({ id, path }) => buildRouteForBundles( - `${basePublicPath}/bundles/plugin:${id}/`, - `/bundles/plugin:${id}/`, + `${basePublicPath}/bundles/plugin/${id}/`, + `/bundles/plugin/${id}/`, path, fileHashCache ) From 784b8beb2f31f163eb82a403aace4d789097299b Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 20 Apr 2020 11:51:53 -0400 Subject: [PATCH 07/17] [ML] DF Analytics Classification exploration: replace table with data grid (#63757) * update classification result to use datagrid * consider isTraining in docCount fetch * fix translations --- .../data_frame_analytics/common/analytics.ts | 22 +- .../classification_exploration_data_grid.tsx | 135 +++++ .../evaluate_panel.tsx | 60 ++- .../results_table.tsx | 470 +++--------------- .../use_explore_data.ts | 226 ++++++--- .../use_explore_data.ts | 4 +- .../translations/translations/ja-JP.json | 7 - .../translations/translations/zh-CN.json | 7 - 8 files changed, 419 insertions(+), 512 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration_data_grid.tsx diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts index 3c959b827bb1c..fb3b2b3519947 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/analytics.ts @@ -52,7 +52,7 @@ export interface ClassificationAnalysis { classification: Classification; } -export interface LoadRegressionExploreDataArg { +export interface LoadExploreDataArg { filterByIsTraining?: boolean; searchQuery: SavedSearchQuery; } @@ -409,11 +409,11 @@ export function getEvalQueryBody({ ignoreDefaultQuery, }: { resultsField: string; - isTraining: boolean; + isTraining?: boolean; searchQuery?: ResultsSearchQuery; ignoreDefaultQuery?: boolean; }) { - let query; + let query: any; const trainingQuery: ResultsSearchQuery = { term: { [`${resultsField}.is_training`]: { value: isTraining } }, @@ -426,19 +426,25 @@ export function getEvalQueryBody({ searchQueryClone.bool.must = []; } - searchQueryClone.bool.must.push(trainingQuery); + if (isTraining !== undefined) { + searchQueryClone.bool.must.push(trainingQuery); + } + query = searchQueryClone; } else if (isQueryStringQuery(searchQueryClone)) { query = { bool: { - must: [searchQueryClone, trainingQuery], + must: [searchQueryClone], }, }; + if (isTraining !== undefined) { + query.bool.must.push(trainingQuery); + } } else { // Not a bool or string query so we need to create it so can add the trainingQuery query = { bool: { - must: [trainingQuery], + must: isTraining !== undefined ? [trainingQuery] : [], }, }; } @@ -456,7 +462,7 @@ interface EvaluateMetrics { } interface LoadEvalDataConfig { - isTraining: boolean; + isTraining?: boolean; index: string; dependentVariable: string; resultsField: string; @@ -535,7 +541,7 @@ interface TrackTotalHitsSearchResponse { interface LoadDocsCountConfig { ignoreDefaultQuery?: boolean; - isTraining: boolean; + isTraining?: boolean; searchQuery: SavedSearchQuery; resultsField: string; destIndex: string; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration_data_grid.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration_data_grid.tsx new file mode 100644 index 0000000000000..424fc002795ca --- /dev/null +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration_data_grid.tsx @@ -0,0 +1,135 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { Dispatch, FC, SetStateAction, useCallback, useMemo } from 'react'; + +import { i18n } from '@kbn/i18n'; + +import { EuiDataGrid, EuiDataGridPaginationProps, EuiDataGridSorting } from '@elastic/eui'; + +import { euiDataGridStyle, euiDataGridToolbarSettings } from '../../../../common'; + +import { mlFieldFormatService } from '../../../../../services/field_format_service'; + +import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; + +const PAGE_SIZE_OPTIONS = [5, 10, 25, 50]; + +type Pagination = Pick; +type TableItem = Record; + +interface ExplorationDataGridProps { + colorRange?: (d: number) => string; + columns: any[]; + indexPattern: IndexPattern; + pagination: Pagination; + resultsField: string; + rowCount: number; + selectedFields: string[]; + setPagination: Dispatch>; + setSelectedFields: Dispatch>; + setSortingColumns: Dispatch>; + sortingColumns: EuiDataGridSorting['columns']; + tableItems: TableItem[]; +} + +export const ClassificationExplorationDataGrid: FC = ({ + columns, + indexPattern, + pagination, + resultsField, + rowCount, + selectedFields, + setPagination, + setSelectedFields, + setSortingColumns, + sortingColumns, + tableItems, +}) => { + const renderCellValue = useMemo(() => { + return ({ rowIndex, columnId }: { rowIndex: number; columnId: string; setCellProps: any }) => { + const adjustedRowIndex = rowIndex - pagination.pageIndex * pagination.pageSize; + + const fullItem = tableItems[adjustedRowIndex]; + + if (fullItem === undefined) { + return null; + } + + let format: any; + + if (indexPattern !== undefined) { + format = mlFieldFormatService.getFieldFormatFromIndexPattern(indexPattern, columnId, ''); + } + + const cellValue = + fullItem.hasOwnProperty(columnId) && fullItem[columnId] !== undefined + ? fullItem[columnId] + : null; + + if (format !== undefined) { + return format.convert(cellValue, 'text'); + } + + if (typeof cellValue === 'string' || cellValue === null) { + return cellValue; + } + + if (typeof cellValue === 'boolean') { + return cellValue ? 'true' : 'false'; + } + + if (typeof cellValue === 'object' && cellValue !== null) { + return JSON.stringify(cellValue); + } + + return cellValue; + }; + }, [resultsField, rowCount, tableItems, pagination.pageIndex, pagination.pageSize]); + + const onChangeItemsPerPage = useCallback( + pageSize => { + setPagination(p => { + const pageIndex = Math.floor((p.pageSize * p.pageIndex) / pageSize); + return { pageIndex, pageSize }; + }); + }, + [setPagination] + ); + + const onChangePage = useCallback(pageIndex => setPagination(p => ({ ...p, pageIndex })), [ + setPagination, + ]); + + const onSort = useCallback(sc => setSortingColumns(sc), [setSortingColumns]); + + return ( + + ); +}; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx index 91dae49ba5c49..af90547606f82 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/evaluate_panel.tsx @@ -117,13 +117,7 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) const resultsField = jobConfig.dest.results_field; let requiresKeyword = false; - const loadData = async ({ - isTrainingClause, - ignoreDefaultQuery = true, - }: { - isTrainingClause: { query: string; operator: string }; - ignoreDefaultQuery?: boolean; - }) => { + const loadData = async ({ isTraining }: { isTraining: boolean | undefined }) => { setIsLoading(true); try { @@ -134,19 +128,18 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) } const evalData = await loadEvalData({ - isTraining: false, + isTraining, index, dependentVariable, resultsField, predictionFieldName, searchQuery, - ignoreDefaultQuery, jobType: ANALYSIS_CONFIG_TYPE.CLASSIFICATION, requiresKeyword, }); const docsCountResp = await loadDocsCount({ - isTraining: false, + isTraining, searchQuery, resultsField, destIndex: jobConfig.dest.index, @@ -225,29 +218,46 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery }) }, [confusionMatrixData]); useEffect(() => { - const hasIsTrainingClause = - isResultsSearchBoolQuery(searchQuery) && - searchQuery.bool.must.filter( - (clause: any) => clause.match && clause.match[`${resultsField}.is_training`] !== undefined - ); - const isTrainingClause = - hasIsTrainingClause && - hasIsTrainingClause[0] && - hasIsTrainingClause[0].match[`${resultsField}.is_training`]; + let isTraining: boolean | undefined; + const query = + isResultsSearchBoolQuery(searchQuery) && (searchQuery.bool.should || searchQuery.bool.filter); - const noTrainingQuery = isTrainingClause === false || isTrainingClause === undefined; + if (query !== undefined && query !== false) { + for (let i = 0; i < query.length; i++) { + const clause = query[i]; - if (noTrainingQuery) { + if (clause.match && clause.match[`${resultsField}.is_training`] !== undefined) { + isTraining = clause.match[`${resultsField}.is_training`]; + break; + } else if ( + clause.bool && + (clause.bool.should !== undefined || clause.bool.filter !== undefined) + ) { + const innerQuery = clause.bool.should || clause.bool.filter; + if (innerQuery !== undefined) { + for (let j = 0; j < innerQuery.length; j++) { + const innerClause = innerQuery[j]; + if ( + innerClause.match && + innerClause.match[`${resultsField}.is_training`] !== undefined + ) { + isTraining = innerClause.match[`${resultsField}.is_training`]; + break; + } + } + } + } + } + } + if (isTraining === undefined) { setDataSubsetTitle(SUBSET_TITLE.ENTIRE); } else { setDataSubsetTitle( - isTrainingClause && isTrainingClause.query === 'true' - ? SUBSET_TITLE.TRAINING - : SUBSET_TITLE.TESTING + isTraining && isTraining === true ? SUBSET_TITLE.TRAINING : SUBSET_TITLE.TESTING ); } - loadData({ isTrainingClause }); + loadData({ isTraining }); }, [JSON.stringify(searchQuery)]); const renderCellValue = ({ diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/results_table.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/results_table.tsx index 9758dd969b443..bf63dfe68fe9e 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/results_table.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/results_table.tsx @@ -4,71 +4,39 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, FC, useEffect, useState } from 'react'; -import moment from 'moment-timezone'; - +import React, { Fragment, FC, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { - EuiBadge, - EuiButtonIcon, EuiCallOut, - EuiCheckbox, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiPanel, - EuiPopover, - EuiPopoverTitle, EuiProgress, EuiSpacer, EuiText, - EuiToolTip, - Query, } from '@elastic/eui'; -import { Query as QueryType } from '../../../analytics_management/components/analytics_list/common'; -import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public'; -import { mlFieldFormatService } from '../../../../../services/field_format_service'; import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public'; - -import { - ColumnType, - mlInMemoryTableBasicFactory, - OnTableChangeArg, - SortingPropType, - SORT_DIRECTION, -} from '../../../../../components/ml_in_memory_table'; - -import { formatHumanReadableDateTimeSeconds } from '../../../../../util/date_utils'; -import { Field } from '../../../../../../../common/types/fields'; -import { SavedSearchQuery } from '../../../../../contexts/ml'; import { BASIC_NUMERICAL_TYPES, EXTENDED_NUMERICAL_TYPES, - isKeywordAndTextType, sortRegressionResultsFields, } from '../../../../common/fields'; import { - toggleSelectedField, - EsDoc, DataFrameAnalyticsConfig, - EsFieldName, MAX_COLUMNS, - getPredictedFieldName, INDEX_STATUS, SEARCH_SIZE, defaultSearchQuery, - getDependentVar, } from '../../../../common'; import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; -import { useExploreData, TableItem } from './use_explore_data'; +import { useExploreData } from './use_explore_data'; // TableItem import { ExplorationTitle } from './classification_exploration'; - -const PAGE_SIZE_OPTIONS = [5, 10, 25, 50]; - -const MlInMemoryTableBasic = mlInMemoryTableBasicFactory(); +import { ClassificationExplorationDataGrid } from './classification_exploration_data_grid'; +import { ExplorationQueryBar } from '../exploration_query_bar'; const showingDocs = i18n.translate( 'xpack.ml.dataframe.analytics.classificationExploration.documentsShownHelpText', @@ -94,307 +62,65 @@ interface Props { export const ResultsTable: FC = React.memo( ({ indexPattern, jobConfig, jobStatus, setEvaluateSearchQuery }) => { - const [pageIndex, setPageIndex] = useState(0); - const [pageSize, setPageSize] = useState(25); - const [selectedFields, setSelectedFields] = useState([] as Field[]); - const [docFields, setDocFields] = useState([] as Field[]); - const [depVarType, setDepVarType] = useState(undefined); - const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false); - const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); - const [searchError, setSearchError] = useState(undefined); - const [searchString, setSearchString] = useState(undefined); - - const predictedFieldName = getPredictedFieldName( - jobConfig.dest.results_field, - jobConfig.analysis - ); - - const dependentVariable = getDependentVar(jobConfig.analysis); - - function toggleColumnsPopover() { - setColumnsPopoverVisible(!isColumnsPopoverVisible); - } - - function closeColumnsPopover() { - setColumnsPopoverVisible(false); - } - - function toggleColumn(column: EsFieldName) { - if (tableItems.length > 0 && jobConfig !== undefined) { - // spread to a new array otherwise the component wouldn't re-render - setSelectedFields([ - ...toggleSelectedField(selectedFields, column, jobConfig.dest.results_field, depVarType), - ]); - } - } - const needsDestIndexFields = indexPattern && indexPattern.title === jobConfig.source.index[0]; - + const resultsField = jobConfig.dest.results_field; const { errorMessage, - loadExploreData, - sortField, - sortDirection, - status, - tableItems, - } = useExploreData( - jobConfig, - needsDestIndexFields, + fieldTypes, + pagination, + searchQuery, selectedFields, + rowCount, + setPagination, + setSearchQuery, setSelectedFields, - setDocFields, - setDepVarType - ); + setSortingColumns, + sortingColumns, + status, + tableFields, + tableItems, + } = useExploreData(jobConfig, needsDestIndexFields); - const columns: Array> = selectedFields - .sort(({ name: a }, { name: b }) => sortRegressionResultsFields(a, b, jobConfig)) - .map(field => { - const { type } = field; - let format: any; + useEffect(() => { + setEvaluateSearchQuery(searchQuery); + }, [JSON.stringify(searchQuery)]); - if (indexPattern !== undefined) { - format = mlFieldFormatService.getFieldFormatFromIndexPattern(indexPattern, field.id, ''); - } + const columns = tableFields + .sort((a: any, b: any) => sortRegressionResultsFields(a, b, jobConfig)) + .map((field: any) => { + // Built-in values are ['boolean', 'currency', 'datetime', 'numeric', 'json'] + // To fall back to the default string schema it needs to be undefined. + let schema; + let isSortable = true; + const type = fieldTypes[field]; const isNumber = type !== undefined && (BASIC_NUMERICAL_TYPES.has(type) || EXTENDED_NUMERICAL_TYPES.has(type)); - const column: ColumnType = { - field: field.name, - name: field.name, - sortable: true, - truncateText: true, - }; - - const render = (d: any, fullItem: EsDoc) => { - if (format !== undefined) { - d = format.convert(d, 'text'); - return d; - } - - if (Array.isArray(d) && d.every(item => typeof item === 'string')) { - // If the cells data is an array of strings, return as a comma separated list. - // The list will get limited to 5 items with `…` at the end if there's more in the original array. - return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`; - } else if (Array.isArray(d)) { - // If the cells data is an array of e.g. objects, display a 'array' badge with a - // tooltip that explains that this type of field is not supported in this table. - return ( - - - {i18n.translate( - 'xpack.ml.dataframe.analytics.classificationExploration.indexArrayBadgeContent', - { - defaultMessage: 'array', - } - )} - - - ); - } - - return d; - }; - if (isNumber) { - column.dataType = 'number'; - column.render = render; - } else if (typeof type !== 'undefined') { - switch (type) { - case ES_FIELD_TYPES.BOOLEAN: - column.dataType = ES_FIELD_TYPES.BOOLEAN; - column.render = d => (d ? 'true' : 'false'); - break; - case ES_FIELD_TYPES.DATE: - column.align = 'right'; - if (format !== undefined) { - column.render = render; - } else { - column.render = (d: any) => { - if (d !== undefined) { - return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000); - } - return d; - }; - } - break; - default: - column.render = render; - break; - } - } else { - column.render = render; + schema = 'numeric'; } - return column; - }); - - const docFieldsCount = docFields.length; - - useEffect(() => { - if ( - jobConfig !== undefined && - columns.length > 0 && - selectedFields.length > 0 && - sortField !== undefined && - sortDirection !== undefined && - selectedFields.some(field => field.name === sortField) - ) { - let field = sortField; - // If sorting by predictedField use dependentVar type - if (predictedFieldName === sortField) { - field = dependentVariable; + switch (type) { + case 'date': + schema = 'datetime'; + break; + case 'geo_point': + schema = 'json'; + break; + case 'boolean': + schema = 'boolean'; + break; } - const requiresKeyword = isKeywordAndTextType(field); - - loadExploreData({ - field: sortField, - direction: sortDirection, - searchQuery, - requiresKeyword, - }); - } - }, [JSON.stringify(searchQuery)]); - - useEffect(() => { - // By default set sorting to descending on the prediction field (`_prediction`). - // if that's not available sort ascending on the first column. Check if the current sorting field is still available. - if ( - jobConfig !== undefined && - columns.length > 0 && - selectedFields.length > 0 && - !selectedFields.some(field => field.name === sortField) - ) { - const predictedFieldSelected = selectedFields.some( - field => field.name === predictedFieldName - ); - - // CHECK IF keyword suffix is needed (if predicted field is selected we have to check the dependent variable type) - let sortByField = predictedFieldSelected ? dependentVariable : selectedFields[0].name; - - const requiresKeyword = isKeywordAndTextType(sortByField); - - sortByField = predictedFieldSelected ? predictedFieldName : sortByField; - - const direction = predictedFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC; - loadExploreData({ field: sortByField, direction, searchQuery, requiresKeyword }); - } - }, [ - jobConfig, - columns.length, - selectedFields.length, - sortField, - sortDirection, - tableItems.length, - ]); - - let sorting: SortingPropType = false; - let onTableChange; - - if (columns.length > 0 && sortField !== '' && sortField !== undefined) { - sorting = { - sort: { - field: sortField, - direction: sortDirection, - }, - }; - - onTableChange = ({ - page = { index: 0, size: 10 }, - sort = { field: sortField, direction: sortDirection }, - }: OnTableChangeArg) => { - const { index, size } = page; - setPageIndex(index); - setPageSize(size); - if (sort.field !== sortField || sort.direction !== sortDirection) { - let field = sort.field; - // If sorting by predictedField use depVar for type check - if (predictedFieldName === sort.field) { - field = dependentVariable; - } - - loadExploreData({ - ...sort, - searchQuery, - requiresKeyword: isKeywordAndTextType(field), - }); + if (field === `${resultsField}.feature_importance`) { + isSortable = false; } - }; - } - const pagination = { - initialPageIndex: pageIndex, - initialPageSize: pageSize, - totalItemCount: tableItems.length, - pageSizeOptions: PAGE_SIZE_OPTIONS, - hidePerPageOptions: false, - }; - - const onQueryChange = ({ query, error }: { query: QueryType; error: any }) => { - if (error) { - setSearchError(error.message); - } else { - try { - const esQueryDsl = Query.toESQuery(query); - setSearchQuery(esQueryDsl); - setSearchString(query.text); - setSearchError(undefined); - // set query for use in evaluate panel - setEvaluateSearchQuery(esQueryDsl); - } catch (e) { - setSearchError(e.toString()); - } - } - }; + return { id: field, schema, isSortable }; + }); - const search = { - onChange: onQueryChange, - defaultQuery: searchString, - box: { - incremental: false, - placeholder: i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.searchBoxPlaceholder', - { - defaultMessage: 'E.g. avg>0.5', - } - ), - }, - filters: [ - { - type: 'field_value_toggle_group', - field: `${jobConfig.dest.results_field}.is_training`, - items: [ - { - value: false, - name: i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.isTestingLabel', - { - defaultMessage: 'Testing', - } - ), - }, - { - value: true, - name: i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.isTrainingLabel', - { - defaultMessage: 'Training', - } - ), - }, - ], - }, - ], - }; + const docFieldsCount = tableFields.length; if (jobConfig === undefined) { return null; @@ -426,11 +152,6 @@ export const ResultsTable: FC = React.memo( ); } - const tableError = - status === INDEX_STATUS.ERROR && errorMessage.includes('parsing_exception') - ? errorMessage - : searchError; - return ( = React.memo( {docFieldsCount > MAX_COLUMNS && ( {i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.fieldSelection', + 'xpack.ml.dataframe.analytics.classificationExploration.fieldSelection', { defaultMessage: '{selectedFieldsLength, number} of {docFieldsCount, number} {docFieldsCount, plural, one {field} other {fields}} selected', @@ -466,52 +187,6 @@ export const ResultsTable: FC = React.memo( )} - - - - } - isOpen={isColumnsPopoverVisible} - closePopover={closeColumnsPopover} - ownFocus - > - - {i18n.translate( - 'xpack.ml.dataframe.analytics.regressionExploration.selectFieldsPopoverTitle', - { - defaultMessage: 'Select fields', - } - )} - -
- {docFields.map(({ name }) => ( - field.name === name)} - onChange={() => toggleColumn(name)} - disabled={ - selectedFields.some(field => field.name === name) && - selectedFields.length === 1 - } - /> - ))} -
-
-
-
@@ -520,28 +195,39 @@ export const ResultsTable: FC = React.memo( )} {(columns.length > 0 || searchQuery !== defaultSearchQuery) && ( - - - - - - - + + + + + + + + + + + + + + + + )}
); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_explore_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_explore_data.ts index 9527a9adb98ce..c8809ca5e471b 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_explore_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_explore_data.ts @@ -3,113 +3,158 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import React, { useEffect, useState } from 'react'; +import { useEffect, useState, Dispatch, SetStateAction } from 'react'; +import { EuiDataGridPaginationProps, EuiDataGridSorting } from '@elastic/eui'; import { SearchResponse } from 'elasticsearch'; import { cloneDeep } from 'lodash'; -import { SortDirection, SORT_DIRECTION } from '../../../../../components/ml_in_memory_table'; +import { SORT_DIRECTION } from '../../../../../components/ml_in_memory_table'; import { ml } from '../../../../../services/ml_api_service'; import { getNestedProperty } from '../../../../../util/object_utils'; import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; -import { Field } from '../../../../../../../common/types/fields'; +import { isKeywordAndTextType } from '../../../../common/fields'; +import { Dictionary } from '../../../../../../../common/types/common'; import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public'; import { defaultSearchQuery, ResultsSearchQuery, isResultsSearchBoolQuery, + LoadExploreDataArg, } from '../../../../common/analytics'; import { getDefaultFieldsFromJobCaps, + getDependentVar, getFlattenedFields, + getPredictedFieldName, DataFrameAnalyticsConfig, EsFieldName, INDEX_STATUS, - SEARCH_SIZE, - SearchQuery, } from '../../../../common'; import { SavedSearchQuery } from '../../../../../contexts/ml'; -interface LoadClassificationExploreDataArg { - direction: SortDirection; - filterByIsTraining?: boolean; - field: string; - searchQuery: SavedSearchQuery; - requiresKeyword?: boolean; - pageIndex?: number; - pageSize?: number; -} - export type TableItem = Record; +type Pagination = Pick; export interface UseExploreDataReturnType { errorMessage: string; - loadExploreData: (arg: LoadClassificationExploreDataArg) => void; - sortField: EsFieldName; - sortDirection: SortDirection; + fieldTypes: { [key: string]: ES_FIELD_TYPES }; + pagination: Pagination; + rowCount: number; + searchQuery: SavedSearchQuery; + selectedFields: EsFieldName[]; + setFilterByIsTraining: Dispatch>; + setPagination: Dispatch>; + setSearchQuery: Dispatch>; + setSelectedFields: Dispatch>; + setSortingColumns: Dispatch>; + sortingColumns: EuiDataGridSorting['columns']; status: INDEX_STATUS; + tableFields: string[]; tableItems: TableItem[]; } +type EsSorting = Dictionary<{ + order: 'asc' | 'desc'; +}>; + +// The types specified in `@types/elasticsearch` are out of date and still have `total: number`. +interface SearchResponse7 extends SearchResponse { + hits: SearchResponse['hits'] & { + total: { + value: number; + relation: string; + }; + }; +} + export const useExploreData = ( - jobConfig: DataFrameAnalyticsConfig | undefined, - needsDestIndexFields: boolean, - selectedFields: Field[], - setSelectedFields: React.Dispatch>, - setDocFields: React.Dispatch>, - setDepVarType: React.Dispatch> + jobConfig: DataFrameAnalyticsConfig, + needsDestIndexFields: boolean ): UseExploreDataReturnType => { const [errorMessage, setErrorMessage] = useState(''); const [status, setStatus] = useState(INDEX_STATUS.UNUSED); + + const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]); + const [tableFields, setTableFields] = useState([]); const [tableItems, setTableItems] = useState([]); - const [sortField, setSortField] = useState(''); - const [sortDirection, setSortDirection] = useState(SORT_DIRECTION.ASC); + const [fieldTypes, setFieldTypes] = useState<{ [key: string]: ES_FIELD_TYPES }>({}); + const [rowCount, setRowCount] = useState(0); + + const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 25 }); + const [searchQuery, setSearchQuery] = useState(defaultSearchQuery); + const [filterByIsTraining, setFilterByIsTraining] = useState(undefined); + const [sortingColumns, setSortingColumns] = useState([]); + + const predictedFieldName = getPredictedFieldName( + jobConfig.dest.results_field, + jobConfig.analysis + ); + const dependentVariable = getDependentVar(jobConfig.analysis); const getDefaultSelectedFields = () => { const { fields } = newJobCapsService; - if (selectedFields.length === 0 && jobConfig !== undefined) { - const { - selectedFields: defaultSelected, - docFields, - depVarType, - } = getDefaultFieldsFromJobCaps(fields, jobConfig, needsDestIndexFields); - - setDepVarType(depVarType); - setSelectedFields(defaultSelected); - setDocFields(docFields); + const { selectedFields: defaultSelected, docFields } = getDefaultFieldsFromJobCaps( + fields, + jobConfig, + needsDestIndexFields + ); + + const types: { [key: string]: ES_FIELD_TYPES } = {}; + const allFields: string[] = []; + + docFields.forEach(field => { + types[field.id] = field.type; + allFields.push(field.id); + }); + + setFieldTypes(types); + setSelectedFields(defaultSelected.map(field => field.id)); + setTableFields(allFields); } }; const loadExploreData = async ({ - field, - direction, - searchQuery, - requiresKeyword, - }: LoadClassificationExploreDataArg) => { + filterByIsTraining: isTraining, + searchQuery: incomingQuery, + }: LoadExploreDataArg) => { if (jobConfig !== undefined) { setErrorMessage(''); setStatus(INDEX_STATUS.LOADING); try { const resultsField = jobConfig.dest.results_field; - const searchQueryClone: ResultsSearchQuery = cloneDeep(searchQuery); + const searchQueryClone: ResultsSearchQuery = cloneDeep(incomingQuery); let query: ResultsSearchQuery; + const { pageIndex, pageSize } = pagination; + // If filterByIsTraining is defined - add that in to the final query + const trainingQuery = + isTraining !== undefined + ? { + term: { [`${resultsField}.is_training`]: { value: isTraining } }, + } + : undefined; - if (JSON.stringify(searchQuery) === JSON.stringify(defaultSearchQuery)) { - query = { + if (JSON.stringify(incomingQuery) === JSON.stringify(defaultSearchQuery)) { + const existsQuery = { exists: { field: resultsField, }, }; + + query = { + bool: { + must: [existsQuery], + }, + }; + + if (trainingQuery !== undefined && isResultsSearchBoolQuery(query)) { + query.bool.must.push(trainingQuery); + } } else if (isResultsSearchBoolQuery(searchQueryClone)) { if (searchQueryClone.bool.must === undefined) { searchQueryClone.bool.must = []; @@ -121,33 +166,37 @@ export const useExploreData = ( }, }); + if (trainingQuery !== undefined) { + searchQueryClone.bool.must.push(trainingQuery); + } + query = searchQueryClone; } else { query = searchQueryClone; } - const body: SearchQuery = { - query, - }; - - if (field !== undefined) { - body.sort = [ - { - [`${field}${requiresKeyword ? '.keyword' : ''}`]: { - order: direction, - }, - }, - ]; - } + const sort: EsSorting = sortingColumns + .map(column => { + const { id } = column; + column.id = isKeywordAndTextType(id) ? `${id}.keyword` : id; + return column; + }) + .reduce((s, column) => { + s[column.id] = { order: column.direction }; + return s; + }, {} as EsSorting); - const resp: SearchResponse = await ml.esSearch({ + const resp: SearchResponse7 = await ml.esSearch({ index: jobConfig.dest.index, - size: SEARCH_SIZE, - body, + body: { + query, + from: pageIndex * pageSize, + size: pageSize, + ...(Object.keys(sort).length > 0 ? { sort } : {}), + }, }); - setSortField(field); - setSortDirection(direction); + setRowCount(resp.hits.total.value); const docs = resp.hits.hits; @@ -199,10 +248,45 @@ export const useExploreData = ( }; useEffect(() => { - if (jobConfig !== undefined) { - getDefaultSelectedFields(); - } + getDefaultSelectedFields(); + }, [jobConfig && jobConfig.id]); + + // By default set sorting to descending on the prediction field (`_prediction`). + useEffect(() => { + const sortByField = isKeywordAndTextType(dependentVariable) + ? `${predictedFieldName}.keyword` + : predictedFieldName; + const direction = SORT_DIRECTION.DESC; + + setSortingColumns([{ id: sortByField, direction }]); }, [jobConfig && jobConfig.id]); - return { errorMessage, loadExploreData, sortField, sortDirection, status, tableItems }; + useEffect(() => { + loadExploreData({ filterByIsTraining, searchQuery }); + }, [ + filterByIsTraining, + jobConfig && jobConfig.id, + pagination, + searchQuery, + selectedFields, + sortingColumns, + ]); + + return { + errorMessage, + fieldTypes, + pagination, + searchQuery, + selectedFields, + rowCount, + setFilterByIsTraining, + setPagination, + setSelectedFields, + setSortingColumns, + setSearchQuery, + sortingColumns, + status, + tableItems, + tableFields, + }; }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts index c68fe5b2cbee8..978aafd10de11 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts @@ -29,7 +29,7 @@ import { Dictionary } from '../../../../../../../common/types/common'; import { isKeywordAndTextType } from '../../../../common/fields'; import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public'; import { - LoadRegressionExploreDataArg, + LoadExploreDataArg, defaultSearchQuery, ResultsSearchQuery, isResultsSearchBoolQuery, @@ -120,7 +120,7 @@ export const useExploreData = ( const loadExploreData = async ({ filterByIsTraining: isTraining, searchQuery: incomingQuery, - }: LoadRegressionExploreDataArg) => { + }: LoadExploreDataArg) => { if (jobConfig !== undefined) { setErrorMessage(''); setStatus(INDEX_STATUS.LOADING); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 4e1217ac9e7b5..39f11ff448292 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9478,8 +9478,6 @@ "xpack.ml.dataframe.analytics.classificationExploration.evaluateJobIdTitle": "分類ジョブID {jobId}の評価", "xpack.ml.dataframe.analytics.classificationExploration.firstDocumentsShownHelpText": "予測がある最初の{searchSize}のドキュメントを示す", "xpack.ml.dataframe.analytics.classificationExploration.generalizationDocsCount": "{docsCount, plural, one {# doc} other {# docs}}が評価されました", - "xpack.ml.dataframe.analytics.classificationExploration.indexArrayBadgeContent": "配列", - "xpack.ml.dataframe.analytics.classificationExploration.indexArrayToolTipContent": "この配列ベースの列の完全なコンテンツは表示できません。", "xpack.ml.dataframe.analytics.classificationExploration.jobCapsFetchError": "結果を取得できません。インデックスのフィールドデータの読み込み中にエラーが発生しました。", "xpack.ml.dataframe.analytics.classificationExploration.jobConfigurationFetchError": "結果を取得できません。ジョブ構成データの読み込み中にエラーが発生しました。", "xpack.ml.dataframe.analytics.classificationExploration.jobConfigurationNoResultsMessage": "結果が見つかりませんでした。", @@ -9574,8 +9572,6 @@ "xpack.ml.dataframe.analytics.regressionExploration.generalizationDocsCount": "{docsCount, plural, one {# doc} other {# docs}}が評価されました", "xpack.ml.dataframe.analytics.regressionExploration.generalizationErrorTitle": "一般化エラー", "xpack.ml.dataframe.analytics.regressionExploration.indexError": "インデックスデータの読み込み中にエラーが発生しました。", - "xpack.ml.dataframe.analytics.regressionExploration.isTestingLabel": "テスト", - "xpack.ml.dataframe.analytics.regressionExploration.isTrainingLabel": "トレーニング", "xpack.ml.dataframe.analytics.regressionExploration.jobCapsFetchError": "結果を取得できません。インデックスのフィールドデータの読み込み中にエラーが発生しました。", "xpack.ml.dataframe.analytics.regressionExploration.jobConfigurationFetchError": "結果を取得できません。ジョブ構成データの読み込み中にエラーが発生しました。", "xpack.ml.dataframe.analytics.regressionExploration.meanSquaredErrorText": "平均二乗エラー", @@ -9587,9 +9583,6 @@ "xpack.ml.dataframe.analytics.regressionExploration.queryParsingErrorMessage": "クエリをパースできません。", "xpack.ml.dataframe.analytics.regressionExploration.rSquaredText": "R の二乗", "xpack.ml.dataframe.analytics.regressionExploration.rSquaredTooltipContent": "適合度を表します。モデルによる観察された結果の複製の効果を測定します。", - "xpack.ml.dataframe.analytics.regressionExploration.searchBoxPlaceholder": "例: 平均>0.5", - "xpack.ml.dataframe.analytics.regressionExploration.selectColumnsAriaLabel": "列を選択", - "xpack.ml.dataframe.analytics.regressionExploration.selectFieldsPopoverTitle": "フィールドを選択", "xpack.ml.dataframe.analytics.regressionExploration.tableJobIdTitle": "回帰ジョブID {jobId}のデスティネーションインデックス", "xpack.ml.dataframe.analytics.regressionExploration.trainingDocsCount": "{docsCount, plural, one {# doc} other {# docs}}が評価されました", "xpack.ml.dataframe.analytics.regressionExploration.trainingErrorTitle": "トレーニングエラー", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index bfdcc8b865313..c24e7d0fa845a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9481,8 +9481,6 @@ "xpack.ml.dataframe.analytics.classificationExploration.evaluateJobIdTitle": "分类作业 ID {jobId} 的评估", "xpack.ml.dataframe.analytics.classificationExploration.firstDocumentsShownHelpText": "正在显示有相关预测存在的前 {searchSize} 个文档", "xpack.ml.dataframe.analytics.classificationExploration.generalizationDocsCount": "{docsCount, plural, one {# 个文档} other {# 个文档}}已评估", - "xpack.ml.dataframe.analytics.classificationExploration.indexArrayBadgeContent": "数组", - "xpack.ml.dataframe.analytics.classificationExploration.indexArrayToolTipContent": "此基于数组的列的完整内容无法显示。", "xpack.ml.dataframe.analytics.classificationExploration.jobCapsFetchError": "无法提取结果。加载索引的字段数据时发生错误。", "xpack.ml.dataframe.analytics.classificationExploration.jobConfigurationFetchError": "无法提取结果。加载作业配置数据时发生错误。", "xpack.ml.dataframe.analytics.classificationExploration.jobConfigurationNoResultsMessage": "未找到结果。", @@ -9577,8 +9575,6 @@ "xpack.ml.dataframe.analytics.regressionExploration.generalizationDocsCount": "{docsCount, plural, one {# 个文档} other {# 个文档}}已评估", "xpack.ml.dataframe.analytics.regressionExploration.generalizationErrorTitle": "泛化误差", "xpack.ml.dataframe.analytics.regressionExploration.indexError": "加载索引数据时出错。", - "xpack.ml.dataframe.analytics.regressionExploration.isTestingLabel": "测试", - "xpack.ml.dataframe.analytics.regressionExploration.isTrainingLabel": "培训", "xpack.ml.dataframe.analytics.regressionExploration.jobCapsFetchError": "无法提取结果。加载索引的字段数据时发生错误。", "xpack.ml.dataframe.analytics.regressionExploration.jobConfigurationFetchError": "无法提取结果。加载作业配置数据时发生错误。", "xpack.ml.dataframe.analytics.regressionExploration.meanSquaredErrorText": "均方误差", @@ -9590,9 +9586,6 @@ "xpack.ml.dataframe.analytics.regressionExploration.queryParsingErrorMessage": "无法解析查询。", "xpack.ml.dataframe.analytics.regressionExploration.rSquaredText": "R 平方", "xpack.ml.dataframe.analytics.regressionExploration.rSquaredTooltipContent": "表示拟合优度。度量模型复制被观察结果的优良性。", - "xpack.ml.dataframe.analytics.regressionExploration.searchBoxPlaceholder": "例如 avg>0.5", - "xpack.ml.dataframe.analytics.regressionExploration.selectColumnsAriaLabel": "选择列", - "xpack.ml.dataframe.analytics.regressionExploration.selectFieldsPopoverTitle": "选择字段", "xpack.ml.dataframe.analytics.regressionExploration.tableJobIdTitle": "回归作业 ID {jobId} 的目标索引", "xpack.ml.dataframe.analytics.regressionExploration.trainingDocsCount": "{docsCount, plural, one {# 个文档} other {# 个文档}}已评估", "xpack.ml.dataframe.analytics.regressionExploration.trainingErrorTitle": "训练误差", From e8c42095d2fff853c67e7000ef093ee6fc6a8c87 Mon Sep 17 00:00:00 2001 From: Uladzislau Lasitsa Date: Mon, 20 Apr 2020 19:03:01 +0300 Subject: [PATCH 08/17] Index pattern management UI -> TypeScript and New Platform Ready (create edit field) (#63836) * Converted to react. Moved routes to edit_index_pattern * Added withRouter for navigation. Fixed index_header. * Fixed comments * Fixed comments. Co-authored-by: Elastic Machine --- .../edit_index_pattern/constants.ts | 22 +++ .../create_edit_field.html | 0 .../create_edit_field/create_edit_field.js | 180 ------------------ .../create_edit_field/create_edit_field.tsx | 111 +++++++++++ .../create_edit_field/{index.js => index.ts} | 2 +- .../edit_index_pattern/edit_index_pattern.js | 98 +++++++++- .../index_header/index_header.tsx | 4 +- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 9 files changed, 227 insertions(+), 192 deletions(-) create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/constants.ts rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/{create_edit_field => }/create_edit_field.html (100%) delete mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js create mode 100644 src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.tsx rename src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/{index.js => index.ts} (93%) diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/constants.ts b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/constants.ts new file mode 100644 index 0000000000000..56da031eb4ee8 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/constants.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const TAB_INDEXED_FIELDS = 'indexedFields'; +export const TAB_SCRIPTED_FIELDS = 'scriptedFields'; +export const TAB_SOURCE_FILTERS = 'sourceFilters'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.html b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field.html similarity index 100% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.html rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field.html diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js deleted file mode 100644 index 95d6cb6878e53..0000000000000 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.js +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { IndexPatternField } from '../../../../../../../../../plugins/data/public'; -import { RegistryFieldFormatEditorsProvider } from 'ui/registry/field_format_editors'; -import { docTitle } from 'ui/doc_title'; -import { KbnUrlProvider } from 'ui/url'; -import uiRoutes from 'ui/routes'; -import { toastNotifications } from 'ui/notify'; -import { npStart } from 'ui/new_platform'; - -import template from './create_edit_field.html'; -import { getEditFieldBreadcrumbs, getCreateFieldBreadcrumbs } from '../../breadcrumbs'; - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { FieldEditor } from 'ui/field_editor'; -import { I18nContext } from 'ui/i18n'; -import { i18n } from '@kbn/i18n'; - -import { IndexHeader } from '../index_header'; - -const REACT_FIELD_EDITOR_ID = 'reactFieldEditor'; -const renderFieldEditor = ( - $scope, - indexPattern, - field, - { getConfig, $http, fieldFormatEditors, redirectAway } -) => { - $scope.$$postDigest(() => { - const node = document.getElementById(REACT_FIELD_EDITOR_ID); - if (!node) { - return; - } - - render( - - - - , - node - ); - }); -}; - -const destroyFieldEditor = () => { - const node = document.getElementById(REACT_FIELD_EDITOR_ID); - node && unmountComponentAtNode(node); -}; - -uiRoutes - .when('/management/kibana/index_patterns/:indexPatternId/field/:fieldName*', { - mode: 'edit', - k7Breadcrumbs: getEditFieldBreadcrumbs, - }) - .when('/management/kibana/index_patterns/:indexPatternId/create-field/', { - mode: 'create', - k7Breadcrumbs: getCreateFieldBreadcrumbs, - }) - .defaults(/management\/kibana\/index_patterns\/[^\/]+\/(field|create-field)(\/|$)/, { - template, - mapBreadcrumbs($route, breadcrumbs) { - const { indexPattern } = $route.current.locals; - return breadcrumbs.map(crumb => { - if (crumb.id !== indexPattern.id) { - return crumb; - } - - return { - ...crumb, - display: indexPattern.title, - }; - }); - }, - resolve: { - indexPattern: function($route, Promise, redirectWhenMissing) { - const { indexPatterns } = npStart.plugins.data; - return Promise.resolve(indexPatterns.get($route.current.params.indexPatternId)).catch( - redirectWhenMissing('/management/kibana/index_patterns') - ); - }, - }, - controllerAs: 'fieldSettings', - controller: function FieldEditorPageController( - $scope, - $route, - $timeout, - $http, - Private, - config - ) { - const getConfig = (...args) => config.get(...args); - const fieldFormatEditors = Private(RegistryFieldFormatEditorsProvider); - const kbnUrl = Private(KbnUrlProvider); - - this.mode = $route.current.mode; - this.indexPattern = $route.current.locals.indexPattern; - - if (this.mode === 'edit') { - const fieldName = $route.current.params.fieldName; - this.field = this.indexPattern.fields.getByName(fieldName); - - if (!this.field) { - const message = i18n.translate('kbn.management.editIndexPattern.scripted.noFieldLabel', { - defaultMessage: - "'{indexPatternTitle}' index pattern doesn't have a scripted field called '{fieldName}'", - values: { indexPatternTitle: this.indexPattern.title, fieldName }, - }); - toastNotifications.add(message); - - kbnUrl.redirectToRoute(this.indexPattern, 'edit'); - return; - } - } else if (this.mode === 'create') { - this.field = new IndexPatternField(this.indexPattern, { - scripted: true, - type: 'number', - }); - } else { - const errorMessage = i18n.translate( - 'kbn.management.editIndexPattern.scripted.unknownModeErrorMessage', - { - defaultMessage: 'unknown fieldSettings mode {mode}', - values: { mode: this.mode }, - } - ); - throw new Error(errorMessage); - } - - const fieldName = - this.field.name || - i18n.translate('kbn.management.editIndexPattern.scripted.newFieldPlaceholder', { - defaultMessage: 'New Scripted Field', - }); - docTitle.change([fieldName, this.indexPattern.title]); - - renderFieldEditor($scope, this.indexPattern, this.field, { - getConfig, - $http, - fieldFormatEditors, - redirectAway: () => { - $timeout(() => { - kbnUrl.changeToRoute( - this.indexPattern, - this.field.scripted ? 'scriptedFields' : 'indexedFields' - ); - }); - }, - }); - - $scope.$on('$destroy', () => { - destroyFieldEditor(); - }); - }, - }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.tsx new file mode 100644 index 0000000000000..4839870f0f3c8 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/create_edit_field.tsx @@ -0,0 +1,111 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React from 'react'; +import { withRouter, RouteComponentProps } from 'react-router-dom'; +// @ts-ignore +import { FieldEditor } from 'ui/field_editor'; + +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { IndexHeader } from '../index_header'; +import { IndexPattern, IndexPatternField } from '../../../../../../../../../plugins/data/public'; +import { ChromeDocTitle, NotificationsStart } from '../../../../../../../../../core/public'; +import { TAB_SCRIPTED_FIELDS, TAB_INDEXED_FIELDS } from '../constants'; + +interface CreateEditFieldProps extends RouteComponentProps { + indexPattern: IndexPattern; + mode?: string; + fieldName?: string; + fieldFormatEditors: any; + getConfig: (name: string) => any; + services: { + notifications: NotificationsStart; + docTitle: ChromeDocTitle; + http: Function; + }; +} + +const newFieldPlaceholder = i18n.translate( + 'kbn.management.editIndexPattern.scripted.newFieldPlaceholder', + { + defaultMessage: 'New Scripted Field', + } +); + +export const CreateEditField = withRouter( + ({ + indexPattern, + mode, + fieldName, + fieldFormatEditors, + getConfig, + services, + history, + }: CreateEditFieldProps) => { + const field = + mode === 'edit' && fieldName + ? indexPattern.fields.getByName(fieldName) + : new IndexPatternField(indexPattern, { + scripted: true, + type: 'number', + }); + + const url = `/management/kibana/index_patterns/${indexPattern.id}`; + + if (mode === 'edit') { + if (!field) { + const message = i18n.translate('kbn.management.editIndexPattern.scripted.noFieldLabel', { + defaultMessage: + "'{indexPatternTitle}' index pattern doesn't have a scripted field called '{fieldName}'", + values: { indexPatternTitle: indexPattern.title, fieldName }, + }); + services.notifications.toasts.addWarning(message); + history.push(url); + } + } + + const docFieldName = field?.name || newFieldPlaceholder; + + services.docTitle.change([docFieldName, indexPattern.title]); + + const redirectAway = () => { + history.push(`${url}?_a=(tab:${field?.scripted ? TAB_SCRIPTED_FIELDS : TAB_INDEXED_FIELDS})`); + }; + + return ( + + + + + + + + + ); + } +); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.ts similarity index 93% rename from src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.js rename to src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.ts index 890a3b2622577..473a8f5b57c82 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/create_edit_field/index.ts @@ -17,4 +17,4 @@ * under the License. */ -import './create_edit_field'; +export { CreateEditField } from './create_edit_field'; diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js index 69184a513f53a..3239a17f109e4 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/edit_index_pattern.js @@ -18,15 +18,18 @@ */ import _ from 'lodash'; +import { HashRouter } from 'react-router-dom'; import { IndexHeader } from './index_header'; -import './create_edit_field'; +import { CreateEditField } from './create_edit_field'; import { docTitle } from 'ui/doc_title'; import { KbnUrlProvider } from 'ui/url'; import { IndicesEditSectionsProvider } from './edit_sections'; import { fatalError, toastNotifications } from 'ui/notify'; +import { RegistryFieldFormatEditorsProvider } from 'ui/registry/field_format_editors'; import uiRoutes from 'ui/routes'; import { uiModules } from 'ui/modules'; import template from './edit_index_pattern.html'; +import createEditFieldtemplate from './create_edit_field.html'; import { fieldWildcardMatcher } from '../../../../../../../../plugins/kibana_utils/public'; import { subscribeWithScope } from '../../../../../../../../plugins/kibana_legacy/public'; import React from 'react'; @@ -37,8 +40,12 @@ import { ScriptedFieldsTable } from './scripted_fields_table'; import { i18n } from '@kbn/i18n'; import { I18nContext } from 'ui/i18n'; import { npStart } from 'ui/new_platform'; - -import { getEditBreadcrumbs } from '../breadcrumbs'; +import { + getEditBreadcrumbs, + getEditFieldBreadcrumbs, + getCreateFieldBreadcrumbs, +} from '../breadcrumbs'; +import { TAB_INDEXED_FIELDS, TAB_SCRIPTED_FIELDS, TAB_SOURCE_FILTERS } from './constants'; import { createEditIndexPatternPageStateContainer } from './edit_index_pattern_state_container'; const REACT_SOURCE_FILTERS_DOM_ELEMENT_ID = 'reactSourceFiltersTable'; @@ -46,10 +53,6 @@ const REACT_INDEXED_FIELDS_DOM_ELEMENT_ID = 'reactIndexedFieldsTable'; const REACT_SCRIPTED_FIELDS_DOM_ELEMENT_ID = 'reactScriptedFieldsTable'; const REACT_INDEX_HEADER_DOM_ELEMENT_ID = 'reactIndexHeader'; -const TAB_INDEXED_FIELDS = 'indexedFields'; -const TAB_SCRIPTED_FIELDS = 'scriptedFields'; -const TAB_SOURCE_FILTERS = 'sourceFilters'; - const EDIT_FIELD_PATH = '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}'; function updateSourceFiltersTable($scope) { @@ -425,3 +428,84 @@ uiModules renderIndexHeader($scope, config); }); + +// routes for create edit field. Will be removed after migartion all component to react. +const REACT_FIELD_EDITOR_ID = 'reactFieldEditor'; +const renderCreateEditField = ($scope, $route, getConfig, $http, fieldFormatEditors) => { + $scope.$$postDigest(() => { + const node = document.getElementById(REACT_FIELD_EDITOR_ID); + if (!node) { + return; + } + + render( + + + + + , + node + ); + }); +}; + +const destroyCreateEditField = () => { + const node = document.getElementById(REACT_FIELD_EDITOR_ID); + node && unmountComponentAtNode(node); +}; + +uiRoutes + .when('/management/kibana/index_patterns/:indexPatternId/field/:fieldName*', { + mode: 'edit', + k7Breadcrumbs: getEditFieldBreadcrumbs, + }) + .when('/management/kibana/index_patterns/:indexPatternId/create-field/', { + mode: 'create', + k7Breadcrumbs: getCreateFieldBreadcrumbs, + }) + .defaults(/management\/kibana\/index_patterns\/[^\/]+\/(field|create-field)(\/|$)/, { + template: createEditFieldtemplate, + mapBreadcrumbs($route, breadcrumbs) { + const { indexPattern } = $route.current.locals; + return breadcrumbs.map(crumb => { + if (crumb.id !== indexPattern.id) { + return crumb; + } + + return { + ...crumb, + display: indexPattern.title, + }; + }); + }, + resolve: { + indexPattern: function($route, Promise, redirectWhenMissing) { + const { indexPatterns } = npStart.plugins.data; + return Promise.resolve(indexPatterns.get($route.current.params.indexPatternId)).catch( + redirectWhenMissing('/management/kibana/index_patterns') + ); + }, + }, + controllerAs: 'fieldSettings', + controller: function FieldEditorPageController($scope, $route, $http, Private, config) { + const getConfig = (...args) => config.get(...args); + const fieldFormatEditors = Private(RegistryFieldFormatEditorsProvider); + + renderCreateEditField($scope, $route, getConfig, $http, fieldFormatEditors); + + $scope.$on('$destroy', () => { + destroyCreateEditField(); + }); + }, + }); diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index_header.tsx b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index_header.tsx index 866d10ecb0e19..deac85d9a32e9 100644 --- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index_header.tsx +++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/index_header/index_header.tsx @@ -30,8 +30,8 @@ import { import { IIndexPattern } from '../../../../../../../../../plugins/data/public'; interface IndexHeaderProps { - defaultIndex: string; indexPattern: IIndexPattern; + defaultIndex?: string; setDefault?: () => void; refreshFields?: () => void; deleteIndexPattern?: () => void; @@ -77,7 +77,7 @@ export function IndexHeader({ )} - +

{indexPattern.title}

diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 39f11ff448292..209a3f626272f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2244,7 +2244,6 @@ "kbn.management.editIndexPattern.scripted.table.nameHeader": "名前", "kbn.management.editIndexPattern.scripted.table.scriptDescription": "フィールドのスクリプトです", "kbn.management.editIndexPattern.scripted.table.scriptHeader": "スクリプト", - "kbn.management.editIndexPattern.scripted.unknownModeErrorMessage": "不明なフィールド設定モード {mode}", "kbn.management.editIndexPattern.scriptedHeader": "スクリプトフィールド", "kbn.management.editIndexPattern.scriptedLabel": "ビジュアライゼーションにスクリプトフィールドを使用し、ドキュメントに表示させることができます。但し、スクリプトフィールドは検索できません。", "kbn.management.editIndexPattern.setDefaultAria": "デフォルトのインデックスに設定", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index c24e7d0fa845a..5d8d733f2b5b6 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2245,7 +2245,6 @@ "kbn.management.editIndexPattern.scripted.table.nameHeader": "名称", "kbn.management.editIndexPattern.scripted.table.scriptDescription": "字段的脚本", "kbn.management.editIndexPattern.scripted.table.scriptHeader": "脚本", - "kbn.management.editIndexPattern.scripted.unknownModeErrorMessage": "未知 fieldSettings 模式 {mode}", "kbn.management.editIndexPattern.scriptedHeader": "脚本字段", "kbn.management.editIndexPattern.scriptedLabel": "可以在可视化中使用脚本字段,并在您的文档中显示它们。但是,您不能搜索脚本字段。", "kbn.management.editIndexPattern.setDefaultAria": "设置为默认索引", From 7db7597a1d5c639ca03b78f0d0746ef4e6c9abdd Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Mon, 20 Apr 2020 12:04:22 -0400 Subject: [PATCH 09/17] [SIEM][Detection Engine] - Move All Rules tabs to match other tabs UI (#63920) ### Summary Restructure All Rules table tabs to be outside of the table, similar to other tabbed tables in UI. --- .../detection_engine/rules/all/index.test.tsx | 192 +++++++++++++++++- .../detection_engine/rules/all/index.tsx | 52 ++++- .../all_rules_tables/index.test.tsx | 74 +++++++ .../components/all_rules_tables/index.tsx | 51 +---- 4 files changed, 323 insertions(+), 46 deletions(-) diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.test.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.test.tsx index f4955c2a93b8d..59b3b02ff3587 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.test.tsx @@ -5,10 +5,138 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, mount } from 'enzyme'; +import { act } from 'react-dom/test-utils'; +import { createKibanaContextProviderMock } from '../../../../mock/kibana_react'; +import { TestProviders } from '../../../../mock'; +import { wait } from '../../../../lib/helpers'; import { AllRules } from './index'; +jest.mock('./reducer', () => { + return { + allRulesReducer: jest.fn().mockReturnValue(() => ({ + exportRuleIds: [], + filterOptions: { + filter: 'some filter', + sortField: 'some sort field', + sortOrder: 'desc', + }, + loadingRuleIds: [], + loadingRulesAction: null, + pagination: { + page: 1, + perPage: 20, + total: 1, + }, + rules: [ + { + actions: [], + created_at: '2020-02-14T19:49:28.178Z', + created_by: 'elastic', + description: 'jibber jabber', + enabled: false, + false_positives: [], + filters: [], + from: 'now-660s', + id: 'rule-id-1', + immutable: true, + index: ['endgame-*'], + interval: '10m', + language: 'kuery', + max_signals: 100, + name: 'Credential Dumping - Detected - Elastic Endpoint', + output_index: '.siem-signals-default', + query: 'host.name:*', + references: [], + risk_score: 73, + rule_id: '571afc56-5ed9-465d-a2a9-045f099f6e7e', + severity: 'high', + tags: ['Elastic', 'Endpoint'], + threat: [], + throttle: null, + to: 'now', + type: 'query', + updated_at: '2020-02-14T19:49:28.320Z', + updated_by: 'elastic', + version: 1, + }, + ], + selectedRuleIds: [], + })), + }; +}); + +jest.mock('../../../../containers/detection_engine/rules', () => { + return { + useRules: jest.fn().mockReturnValue([ + false, + { + page: 1, + perPage: 20, + total: 1, + data: [ + { + actions: [], + created_at: '2020-02-14T19:49:28.178Z', + created_by: 'elastic', + description: 'jibber jabber', + enabled: false, + false_positives: [], + filters: [], + from: 'now-660s', + id: 'rule-id-1', + immutable: true, + index: ['endgame-*'], + interval: '10m', + language: 'kuery', + max_signals: 100, + name: 'Credential Dumping - Detected - Elastic Endpoint', + output_index: '.siem-signals-default', + query: 'host.name:*', + references: [], + risk_score: 73, + rule_id: '571afc56-5ed9-465d-a2a9-045f099f6e7e', + severity: 'high', + tags: ['Elastic', 'Endpoint'], + threat: [], + throttle: null, + to: 'now', + type: 'query', + updated_at: '2020-02-14T19:49:28.320Z', + updated_by: 'elastic', + version: 1, + }, + ], + }, + ]), + useRulesStatuses: jest.fn().mockReturnValue({ + loading: false, + rulesStatuses: [ + { + current_status: { + alert_id: 'alertId', + bulk_create_time_durations: ['2235.01'], + gap: null, + last_failure_at: null, + last_failure_message: null, + last_look_back_date: new Date().toISOString(), + last_success_at: new Date().toISOString(), + last_success_message: 'it is a success', + search_after_time_durations: ['616.97'], + status: 'succeeded', + status_date: new Date().toISOString(), + }, + failures: [], + id: '12345678987654321', + activate: true, + name: 'Test rule', + }, + ], + }), + }; +}); + jest.mock('react-router-dom', () => { const originalModule = jest.requireActual('react-router-dom'); @@ -37,4 +165,66 @@ describe('AllRules', () => { expect(wrapper.find('[title="All rules"]')).toHaveLength(1); }); + + it('renders rules tab', async () => { + const KibanaContext = createKibanaContextProviderMock(); + const wrapper = mount( + + + + + + ); + + await act(async () => { + await wait(); + + expect(wrapper.exists('[data-test-subj="monitoring-table"]')).toBeFalsy(); + expect(wrapper.exists('[data-test-subj="rules-table"]')).toBeTruthy(); + }); + }); + + it('renders monitoring tab when monitoring tab clicked', async () => { + const KibanaContext = createKibanaContextProviderMock(); + + const wrapper = mount( + + + + + + ); + const monitoringTab = wrapper.find('[data-test-subj="allRulesTableTab-monitoring"] button'); + monitoringTab.simulate('click'); + + await act(async () => { + wrapper.update(); + await wait(); + + expect(wrapper.exists('[data-test-subj="monitoring-table"]')).toBeTruthy(); + expect(wrapper.exists('[data-test-subj="rules-table"]')).toBeFalsy(); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx index e96ed856208bd..18ca4d42bd018 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/all/index.tsx @@ -4,7 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiBasicTable, EuiContextMenuPanel, EuiLoadingContent, EuiSpacer } from '@elastic/eui'; +import { + EuiBasicTable, + EuiContextMenuPanel, + EuiLoadingContent, + EuiSpacer, + EuiTab, + EuiTabs, +} from '@elastic/eui'; import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'; import { useHistory } from 'react-router-dom'; import uuid from 'uuid'; @@ -75,6 +82,24 @@ interface AllRulesProps { setRefreshRulesData: (refreshRule: (refreshPrePackagedRule?: boolean) => void) => void; } +export enum AllRulesTabs { + rules = 'rules', + monitoring = 'monitoring', +} + +const allRulesTabs = [ + { + id: AllRulesTabs.rules, + name: i18n.RULES_TAB, + disabled: false, + }, + { + id: AllRulesTabs.monitoring, + name: i18n.MONITORING_TAB, + disabled: false, + }, +]; + /** * Table Component for displaying all Rules for a given cluster. Provides the ability to filter * by name, sort by enabled, and perform the following actions: @@ -114,6 +139,7 @@ export const AllRules = React.memo( const history = useHistory(); const [, dispatchToaster] = useStateToaster(); const mlCapabilities = useMlCapabilities(); + const [allRulesTab, setAllRulesTab] = useState(AllRulesTabs.rules); // TODO: Refactor license check + hasMlAdminPermissions to common check const hasMlPermissions = @@ -271,6 +297,25 @@ export const AllRules = React.memo( return false; }, [loadingRuleIds, loadingRulesAction]); + const tabs = useMemo( + () => ( + + {allRulesTabs.map(tab => ( + setAllRulesTab(tab.id)} + isSelected={tab.id === allRulesTab} + disabled={tab.disabled} + key={tab.id} + > + {tab.name} + + ))} + + ), + [allRulesTabs, allRulesTab, setAllRulesTab] + ); + return ( <> ( exportSelectedData={exportRules} /> + {tabs} + <> @@ -321,7 +368,7 @@ export const AllRules = React.memo( )} {showRulesTable({ rulesCustomInstalled, rulesInstalled }) && !initLoading && ( <> - + @@ -352,6 +399,7 @@ export const AllRules = React.memo( { it('renders correctly', () => { @@ -16,6 +17,7 @@ describe('AllRulesTables', () => { return ( { expect(wrapper.dive().find('[data-test-subj="rules-table"]')).toHaveLength(1); }); + + it('renders rules tab when "selectedTab" is "rules"', () => { + const Component = () => { + const ref = useRef(); + + return ( + + ); + }; + const wrapper = shallow(); + + expect(wrapper.dive().find('[data-test-subj="rules-table"]')).toHaveLength(1); + expect(wrapper.dive().find('[data-test-subj="monitoring-table"]')).toHaveLength(0); + }); + + it('renders monitoring tab when "selectedTab" is "monitoring"', () => { + const Component = () => { + const ref = useRef(); + + return ( + + ); + }; + const wrapper = shallow(); + + expect(wrapper.dive().find('[data-test-subj="rules-table"]')).toHaveLength(0); + expect(wrapper.dive().find('[data-test-subj="monitoring-table"]')).toHaveLength(1); + }); }); diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx index 31aaa426e4f3b..8ea5606d0082c 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/components/all_rules_tables/index.tsx @@ -7,13 +7,11 @@ import { EuiBasicTable, EuiBasicTableColumn, - EuiTab, - EuiTabs, EuiEmptyPrompt, Direction, EuiTableSelectionType, } from '@elastic/eui'; -import React, { useMemo, memo, useState } from 'react'; +import React, { useMemo, memo } from 'react'; import styled from 'styled-components'; import { EuiBasicTableOnChange } from '../../types'; @@ -23,6 +21,7 @@ import { RuleStatusRowItemType, } from '../../../../../pages/detection_engine/rules/all/columns'; import { Rule, Rules } from '../../../../../containers/detection_engine/rules'; +import { AllRulesTabs } from '../../all'; // EuiBasicTable give me a hardtime with adding the ref attributes so I went the easy way // after few hours of fight with typescript !!!! I lost :( @@ -57,27 +56,10 @@ interface AllRulesTablesProps { }; tableOnChangeCallback: ({ page, sort }: EuiBasicTableOnChange) => void; tableRef?: React.MutableRefObject; + selectedTab: AllRulesTabs; } -enum AllRulesTabs { - rules = 'rules', - monitoring = 'monitoring', -} - -const allRulesTabs = [ - { - id: AllRulesTabs.rules, - name: i18n.RULES_TAB, - disabled: false, - }, - { - id: AllRulesTabs.monitoring, - name: i18n.MONITORING_TAB, - disabled: false, - }, -]; - -const AllRulesTablesComponent: React.FC = ({ +export const AllRulesTablesComponent: React.FC = ({ euiBasicTableSelectionProps, hasNoPermissions, monitoringColumns, @@ -88,34 +70,17 @@ const AllRulesTablesComponent: React.FC = ({ sorting, tableOnChangeCallback, tableRef, + selectedTab, }) => { - const [allRulesTab, setAllRulesTab] = useState(AllRulesTabs.rules); const emptyPrompt = useMemo(() => { return ( {i18n.NO_RULES}} titleSize="xs" body={i18n.NO_RULES_BODY} /> ); }, []); - const tabs = useMemo( - () => ( - - {allRulesTabs.map(tab => ( - setAllRulesTab(tab.id)} - isSelected={tab.id === allRulesTab} - disabled={tab.disabled} - key={tab.id} - > - {tab.name} - - ))} - - ), - [allRulesTabs, allRulesTab, setAllRulesTab] - ); + return ( <> - {tabs} - {allRulesTab === AllRulesTabs.rules && ( + {selectedTab === AllRulesTabs.rules && ( = ({ selection={hasNoPermissions ? undefined : euiBasicTableSelectionProps} /> )} - {allRulesTab === AllRulesTabs.monitoring && ( + {selectedTab === AllRulesTabs.monitoring && ( Date: Mon, 20 Apr 2020 09:09:49 -0700 Subject: [PATCH 10/17] [DOCS] Alerting PagerDuty benefits (#63652) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [DOCS] Alerting PagerDuty benefits * [DOCS] Fixes broken link * [DOCS] Organization changes * [DOCS] Changes to meet template and incorporate review comments * [DOCS] Fixed formatting of bulleted list * [DOCS] Incorporates review comments * Update docs/user/alerting/action-types/pagerduty.asciidoc Co-Authored-By: Mike Côté * [DOCS] Fixes naming and other formatting issues Co-authored-by: Mike Côté --- .../alerting/action-types/pagerduty.asciidoc | 133 +++++++++++++++++- .../alerting/images/pagerduty-integration.png | Bin 0 -> 88629 bytes 2 files changed, 128 insertions(+), 5 deletions(-) create mode 100755 docs/user/alerting/images/pagerduty-integration.png diff --git a/docs/user/alerting/action-types/pagerduty.asciidoc b/docs/user/alerting/action-types/pagerduty.asciidoc index 50a1f31e4a9ae..da34c6e0855d7 100644 --- a/docs/user/alerting/action-types/pagerduty.asciidoc +++ b/docs/user/alerting/action-types/pagerduty.asciidoc @@ -4,19 +4,142 @@ The PagerDuty action type uses the https://v2.developer.pagerduty.com/docs/events-api-v2[v2 Events API] to trigger, acknowledge, and resolve PagerDuty alerts. +* <> +* <> +* <> + +[float] +[[pagerduty-benefits]] +=== PagerDuty + Elastic integration benefits + +By integrating PagerDuty with alerts, you can: + +* Route your alerts to the right PagerDuty responder within your team, based on your structure, escalation policies, and workflows. +* Automatically generate incidents of different types and severity based on each alert’s context. +* Tailor the incident data to match your needs by easily passing the alerting context from Kibana to PagerDuty. + +[float] +[[pagerduty-how-it-works]] +==== How it works + +{kib} allows you to create alerts to notify you of a significant move +in your dataset. +You can create alerts for all your Observability, Security, and Elastic Stack use cases. +Alerts will trigger a new incident on the corresponding PagerDuty service. + +[float] +==== Requirements + +In the `kibana.yml` configuration file, you must add the <>. +This is required to encrypt parameters that must be secured, for example PagerDuty’s integration key. + +If you have security enabled: + +* You must have +application privileges to access Metrics, APM, Uptime, or SIEM. +* If you are using a self-managed deployment with security, you must have +Transport Security Layer (TLS) enabled for communication <>. +Alerts uses API keys to secure background alert checks and actions, +and API keys require {ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. + +Although not a requirement, to harden the integrations security you might want to +review the <> that are available to you. + +[float] +[[pagerduty-support]] +==== Support +If you need help with this integration, get in touch with the {kib} team by visiting +https://support.elastic.co[support.elastic.co] or by using the *Ask Elastic* option in the {kib} Help menu. +You can also select the {kib} category at https://discuss.elastic.co/[discuss.elastic.co]. + +[float] +[[pagerduty-integration-walkthrough]] +==== Integration with PagerDuty walkthrough + +[float] +[[pagerduty-in-pagerduty]] +===== In PagerDuty + +. From the *Configuration* menu, select *Services*. +. Add an integration to a service: ++ +* If you are adding your integration to an existing service, +click the name of the service you want to add the integration to. +Then, select the *Integrations* tab and click the *New Integration* button. +* If you are creating a new service for your integration, +go to +https://support.pagerduty.com/docs/services-and-integrations#section-configuring-services-and-integrations[Configuring Services and Integrations] +and follow the steps outlined in the *Create a New Service* section, selecting *Elastic* as the *Integration Type* in step 4. +Continue with the <> section once you have finished these steps. + +. Enter an *Integration Name* in the format Elastic-service-name (for example, Elastic-Alerting or Kibana-APM-Alerting) +and select Elastic from the *Integration Type* menu. +. Click *Add Integration* to save your new integration. ++ +You will be redirected to the *Integrations* tab for your service. An Integration Key is generated on this screen. ++ +[role="screenshot"] +image::user/alerting/images/pagerduty-integration.png[PagerDuty Integrations tab] + +. Save this key, as you will use it when you configure the integration with Elastic in the next section. + +[float] +[[pagerduty-in-elastic]] +===== In Elastic + +. Create a PagerDuty Connector in Kibana. You can: ++ +* Create a connector as part of creating an alert by selecting PagerDuty in the *Actions* +section of the alert configuration and selecting *Add new*. +* Alternatively, create a connector by navigating to *Management* from the {kib} navbar and selecting +*Alerts and Actions*. Then, select the *Connectors* tab, click the *Create connector* button, and select the PagerDuty option. + +. Configure the connector by giving it a name and optionally entering the API URL and Routing Key, or using the defaults. ++ +See <> for how to obtain the endpoint and key information from PagerDuty and +<> for more details. + +. Save the Connector. + +. Create an alert using *Management > Alerts and Actions* or the application of your choice. + +. Set up an action using your PagerDuty connector, by determining: ++ +* The action’s type: Trigger, Resolve, or Acknowledge. +* The event’s severity: Info, warning, error, or critical. +* An array of different fields, including the timestamp, group, class, component, and your dedup key. +Depending on your custom needs, assign them variables from the alerting context. +To see the available context variables, click on the *Add alert variable* icon next +to each corresponding field. For more details on these parameters, see the +<> and the PagerDuty +https://v2.developer.pagerduty.com/v2/docs/send-an-event-events-api-v2[API v2 documentation]. + + +[float] +[[pagerduty-uninstall]] +==== How to uninstall +To remove a PagerDuty connector from an alert, simply remove it +from the *Actions* section of that alert, using the remove (x) icon. +This will disable the integration for the particular alert. + +To delete the connector entirely, go to *Management > Alerts and Actions*. +Select the *Connectors* tab, and then click on the delete icon. +This is an irreversible action and impacts all alerts that use this connector. + + [float] [[pagerduty-connector-configuration]] -==== Connector configuration +=== Connector configuration PagerDuty connectors have the following configuration properties: Name:: The name of the connector. The name is used to identify a connector in the management UI connector listing, or in the connector list when configuring an action. -API URL:: An optional PagerDuty event URL. Defaults to `https://events.pagerduty.com/v2/enqueue`. If you are using the <> setting, make sure the hostname is whitelisted. +API URL:: An optional PagerDuty event URL. Defaults to `https://events.pagerduty.com/v2/enqueue`. If you are using the <> setting, make sure the hostname is whitelisted. Routing Key:: A 32 character PagerDuty Integration Key for an integration on a service or on a global ruleset. [float] [[pagerduty-action-configuration]] -==== Action configuration +=== Action configuration PagerDuty actions have the following properties: @@ -26,8 +149,8 @@ Dedup Key:: All actions sharing this key will be associated with the same Pa Timestamp:: An *optional* https://v2.developer.pagerduty.com/v2/docs/types#datetime[ISO-8601 format date-time], indicating the time the event was detected or generated. Component:: An *optional* value indicating the component of the source machine that is responsible for the event, for example `mysql` or `eth0`. Group:: An *optional* value indicating the logical grouping of components of a service, for example `app-stack`. -Source:: An *optional* value indicating the affected system, preferably a hostname or fully qualified domain name. Defaults to the {kib} saved object id of the action. +Source:: An *optional* value indicating the affected system, preferably a hostname or fully qualified domain name. Defaults to the {kib} saved object id of the action. Summary:: An *optional* text summary of the event, defaults to `No summary provided`. The maximum length is 1024 characters. Class:: An *optional* value indicating the class/type of the event, for example `ping failure` or `cpu load`. -For more details on these properties, see https://v2.developer.pagerduty.com/v2/docs/send-an-event-events-api-v2[PagerDuty v2 event parameters]. \ No newline at end of file +For more details on these properties, see https://v2.developer.pagerduty.com/v2/docs/send-an-event-events-api-v2[PagerDuty v2 event parameters]. diff --git a/docs/user/alerting/images/pagerduty-integration.png b/docs/user/alerting/images/pagerduty-integration.png new file mode 100755 index 0000000000000000000000000000000000000000..0a270de866b36e6d602ecc06d07bc0c3780d9e9e GIT binary patch literal 88629 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 b`hZ;$PZ5QcGLilW^-_>gep@1C{N?`uD)C+% literal 0 HcmV?d00001 From 44a2c2f8f75dad84c792e15050a50c3aa8048875 Mon Sep 17 00:00:00 2001 From: Henry Harding Date: Mon, 20 Apr 2020 12:10:15 -0400 Subject: [PATCH 11/17] Ingest overview page (#63214) * use fixed table layout * added markup structure / css for overview page * add flyout and links to other pages * add "alpha" messaging at bottom of all pages * attrs instead of defaultProps on styled components * use FormattedMessage on alpha messaging component * remove leftover code * remove unused import --- .../components/alpha_messaging.tsx | 37 ++++ .../ingest_manager/components/index.ts | 1 + .../ingest_manager/layouts/default.tsx | 4 + .../ingest_manager/layouts/with_header.tsx | 2 + .../ingest_manager/layouts/without_header.tsx | 2 + .../sections/overview/index.tsx | 204 +++++++++++++++++- 6 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.tsx new file mode 100644 index 0000000000000..0f3ddee29fa44 --- /dev/null +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/alpha_messaging.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; + * you may not use this file except in compliance with the Elastic License. + */ +import React from 'react'; +import styled from 'styled-components'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiText } from '@elastic/eui'; + +const Message = styled(EuiText).attrs(props => ({ + color: 'subdued', + textAlign: 'center', +}))` + padding: ${props => props.theme.eui.paddingSizes.m}; +`; + +export const AlphaMessaging: React.FC<{}> = () => ( + +

+ + + + + {' – '} + + +

+
+); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/index.ts b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/index.ts index 5551bff2c8bde..bdc8f350f7108 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/index.ts +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/components/index.ts @@ -6,3 +6,4 @@ export { Loading } from './loading'; export { Error } from './error'; export { Header, HeaderProps } from './header'; +export { AlphaMessaging } from './alpha_messaging'; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index 26f2c85a291a3..f797c509bfca0 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -8,6 +8,7 @@ import styled from 'styled-components'; import { EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { Section } from '../sections'; +import { AlphaMessaging } from '../components'; import { useLink, useConfig } from '../hooks'; import { EPM_PATH, FLEET_PATH, AGENT_CONFIG_PATH } from '../constants'; @@ -19,6 +20,8 @@ interface Props { const Container = styled.div` min-height: calc(100vh - ${props => props.theme.eui.euiHeaderChildSize}); background: ${props => props.theme.eui.euiColorEmptyShade}; + display: flex; + flex-direction: column; `; const Nav = styled.nav` @@ -80,6 +83,7 @@ export const DefaultLayout: React.FunctionComponent = ({ section, childre {children} + ); }; diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/with_header.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/with_header.tsx index c77a50d95dca3..bb867718204b2 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/with_header.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/with_header.tsx @@ -10,6 +10,8 @@ import { Header, HeaderProps } from '../components'; const Page = styled(EuiPage)` background: ${props => props.theme.eui.euiColorEmptyShade}; + flex: 1; + align-items: flex-start; `; interface Props extends HeaderProps { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/without_header.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/without_header.tsx index cad98c5a0a7e1..9f9fa03942c09 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/without_header.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/without_header.tsx @@ -9,6 +9,8 @@ import { EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui'; const Page = styled(EuiPage)` background: ${props => props.theme.eui.euiColorEmptyShade}; + flex: 1; + align-items: flex-start; `; interface Props { diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx index ea6b045f504ec..05d150fd9ae23 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/overview/index.tsx @@ -3,12 +3,71 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { EuiText, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React, { useState } from 'react'; +import styled from 'styled-components'; +import { + EuiButton, + EuiButtonEmpty, + EuiPanel, + EuiText, + EuiTitle, + EuiDescriptionList, + EuiDescriptionListDescription, + EuiDescriptionListTitle, + EuiFlexGrid, + EuiFlexGroup, + EuiFlexItem, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { WithHeaderLayout } from '../../layouts'; +import { useLink, useGetAgentConfigs } from '../../hooks'; +import { AgentEnrollmentFlyout } from '../fleet/agent_list_page/components'; +import { EPM_PATH, FLEET_PATH, AGENT_CONFIG_PATH } from '../../constants'; + +const OverviewPanel = styled(EuiPanel).attrs(props => ({ + paddingSize: 'm', +}))` + header { + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid ${props => props.theme.eui.euiColorLightShade}; + margin: -${props => props.theme.eui.paddingSizes.m} -${props => props.theme.eui.paddingSizes.m} + ${props => props.theme.eui.paddingSizes.m}; + padding: ${props => props.theme.eui.paddingSizes.s} ${props => props.theme.eui.paddingSizes.m}; + } + + h2 { + padding: ${props => props.theme.eui.paddingSizes.xs} 0; + } +`; + +const OverviewStats = styled(EuiDescriptionList).attrs(props => ({ + compressed: true, + textStyle: 'reverse', + type: 'column', +}))` + & > * { + margin-top: ${props => props.theme.eui.paddingSizes.s} !important; + + &:first-child, + &:nth-child(2) { + margin-top: 0 !important; + } + } +`; export const IngestManagerOverview: React.FunctionComponent = () => { + // Agent enrollment flyout state + const [isEnrollmentFlyoutOpen, setIsEnrollmentFlyoutOpen] = useState(false); + + // Agent configs required for enrollment flyout + const agentConfigsRequest = useGetAgentConfigs({ + page: 1, + perPage: 1000, + }); + const agentConfigs = agentConfigsRequest.data ? agentConfigsRequest.data.items : []; + return ( {

} - /> + rightColumn={ + + + setIsEnrollmentFlyoutOpen(true)}> + + + + + } + > + {isEnrollmentFlyoutOpen && ( + setIsEnrollmentFlyoutOpen(false)} + /> + )} + + + + +
+ +

+ +

+
+ + + +
+ + Total available + 999 + Installed + 1 + Updated available + 0 + +
+
+ + + +
+ +

+ +

+
+ + + +
+ + Total configs + 1 + Data sources + 1 + +
+
+ + + +
+ +

+ +

+
+ + + +
+ + Total agents + 0 + Active + 0 + Offline + 0 + Error + 0 + +
+
+ + + +
+ +

+ +

+
+ + + +
+ + Data streams + 0 + Name spaces + 0 + Total size + 0 MB + +
+
+
+ ); }; From 7e3de56303d39e284e94216df19ff70c712b9e47 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Mon, 20 Apr 2020 12:43:21 -0400 Subject: [PATCH 12/17] [TSVB] Use default Kibana palette for split series (#62241) * [TSVB] Rainbow palette shares colors with dashboard * Add migration * Add charts as NP dependency Co-authored-by: Elastic Machine --- src/plugins/vis_type_timeseries/kibana.json | 2 +- .../components/vis_types/timeseries/config.js | 15 ++- .../visualizations/views/timeseries/index.js | 14 ++- .../public/metrics_type.ts | 1 + .../vis_type_timeseries/public/plugin.ts | 6 +- .../vis_type_timeseries/public/services.ts | 5 + .../lib/vis_data/helpers/get_split_colors.js | 4 +- .../lib/vis_data/helpers/get_splits.test.js | 117 +++++++++++++----- .../visualization_migrations.test.ts | 58 +++++++++ .../saved_objects/visualization_migrations.ts | 33 +++++ .../apps/visualize/_tsvb_time_series.ts | 9 +- .../page_objects/visual_builder_page.ts | 4 + 12 files changed, 218 insertions(+), 50 deletions(-) diff --git a/src/plugins/vis_type_timeseries/kibana.json b/src/plugins/vis_type_timeseries/kibana.json index 38662c6a7ff89..9053d2543e0d0 100644 --- a/src/plugins/vis_type_timeseries/kibana.json +++ b/src/plugins/vis_type_timeseries/kibana.json @@ -4,6 +4,6 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["data", "expressions", "visualizations"], + "requiredPlugins": ["charts", "data", "expressions", "visualizations"], "optionalPlugins": ["usageCollection"] } diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js b/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js index 024f59c3abb1c..d29b795b10ec8 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_types/timeseries/config.js @@ -53,7 +53,7 @@ export const TimeseriesConfig = injectI18n(function(props) { point_size: '', value_template: '{{value}}', offset_time: '', - split_color_mode: 'gradient', + split_color_mode: 'kibana', axis_min: '', axis_max: '', stacked: STACKED_OPTIONS.NONE, @@ -140,10 +140,10 @@ export const TimeseriesConfig = injectI18n(function(props) { const splitColorOptions = [ { label: intl.formatMessage({ - id: 'visTypeTimeseries.timeSeries.gradientLabel', - defaultMessage: 'Gradient', + id: 'visTypeTimeseries.timeSeries.defaultPaletteLabel', + defaultMessage: 'Default palette', }), - value: 'gradient', + value: 'kibana', }, { label: intl.formatMessage({ @@ -152,6 +152,13 @@ export const TimeseriesConfig = injectI18n(function(props) { }), value: 'rainbow', }, + { + label: intl.formatMessage({ + id: 'visTypeTimeseries.timeSeries.gradientLabel', + defaultMessage: 'Gradient', + }), + value: 'gradient', + }, ]; const selectedSplitColorOption = splitColorOptions.find(option => { return model.split_color_mode === option.value; diff --git a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/index.js b/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/index.js index b1c3c7ac6b67a..5cf1619150e5c 100644 --- a/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/index.js +++ b/src/plugins/vis_type_timeseries/public/application/visualizations/views/timeseries/index.js @@ -33,7 +33,7 @@ import { import { EuiIcon } from '@elastic/eui'; import { getTimezone } from '../../../lib/get_timezone'; import { eventBus, ACTIVE_CURSOR } from '../../lib/active_cursor'; -import { getUISettings } from '../../../../services'; +import { getUISettings, getChartsSetup } from '../../../../services'; import { GRID_LINE_CONFIG, ICON_TYPES_MAP, STACKED_OPTIONS } from '../../constants'; import { AreaSeriesDecorator } from './decorators/area_decorator'; import { BarSeriesDecorator } from './decorators/bar_decorator'; @@ -94,6 +94,12 @@ export const TimeSeries = ({ // apply legend style change if bgColor is configured const classes = classNames('tvbVisTimeSeries', getChartClasses(backgroundColor)); + // If the color isn't configured by the user, use the color mapping service + // to assign a color from the Kibana palette. Colors will be shared across the + // session, including dashboards. + const { colors } = getChartsSetup(); + colors.mappedColors.mapKeys(series.filter(({ color }) => !color).map(({ label }) => label)); + return ( ; visualizations: VisualizationsSetup; + charts: ChartsPluginSetup; } /** @internal */ @@ -56,10 +59,11 @@ export class MetricsPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { expressions, visualizations }: MetricsPluginSetupDependencies + { expressions, visualizations, charts }: MetricsPluginSetupDependencies ) { expressions.registerFunction(createMetricsFn); setUISettings(core.uiSettings); + setChartsSetup(charts); visualizations.createReactVisualization(metricsVisDefinition); } diff --git a/src/plugins/vis_type_timeseries/public/services.ts b/src/plugins/vis_type_timeseries/public/services.ts index d93a376584eac..9aa84478fb78b 100644 --- a/src/plugins/vis_type_timeseries/public/services.ts +++ b/src/plugins/vis_type_timeseries/public/services.ts @@ -19,6 +19,7 @@ import { I18nStart, SavedObjectsStart, IUiSettingsClient, CoreStart } from 'src/core/public'; import { createGetterSetter } from '../../kibana_utils/public'; +import { ChartsPluginSetup } from '../../charts/public'; import { DataPublicPluginStart } from '../../data/public'; export const [getUISettings, setUISettings] = createGetterSetter('UISettings'); @@ -36,3 +37,7 @@ export const [getCoreStart, setCoreStart] = createGetterSetter('CoreS export const [getDataStart, setDataStart] = createGetterSetter('DataStart'); export const [getI18n, setI18n] = createGetterSetter('I18n'); + +export const [getChartsSetup, setChartsSetup] = createGetterSetter( + 'ChartsPluginSetup' +); diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_split_colors.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_split_colors.js index ff8d9077b0871..cad8c8f2025a1 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_split_colors.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_split_colors.js @@ -19,7 +19,7 @@ import Color from 'color'; -export function getSplitColors(inputColor, size = 10, style = 'gradient') { +export function getSplitColors(inputColor, size = 10, style = 'kibana') { const color = new Color(inputColor); const colors = []; let workingColor = Color.hsl(color.hsl().object()); @@ -49,7 +49,7 @@ export function getSplitColors(inputColor, size = 10, style = 'gradient') { '#0F1419', '#666666', ]; - } else { + } else if (style === 'gradient') { colors.push(color.string()); const rotateBy = color.luminosity() / (size - 1); for (let i = 0; i < size - 1; i++) { diff --git a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js index 0874d944033f5..376d32d0da13f 100644 --- a/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js +++ b/src/plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js @@ -106,7 +106,7 @@ describe('getSplits(resp, panel, series)', () => { ]); }); - test('should return a splits for terms group bys', () => { + describe('terms group bys', () => { const resp = { aggregations: { SERIES: { @@ -126,38 +126,89 @@ describe('getSplits(resp, panel, series)', () => { }, }, }; - const series = { - id: 'SERIES', - color: '#F00', - split_mode: 'terms', - terms_field: 'beat.hostname', - terms_size: 10, - metrics: [ - { id: 'AVG', type: 'avg', field: 'cpu' }, - { id: 'SIBAGG', type: 'avg_bucket', field: 'AVG' }, - ], - }; - const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).toEqual([ - { - id: 'SERIES:example-01', - key: 'example-01', - label: 'example-01', - meta: { bucketSize: 10 }, - color: 'rgb(255, 0, 0)', - timeseries: { buckets: [] }, - SIBAGG: { value: 1 }, - }, - { - id: 'SERIES:example-02', - key: 'example-02', - label: 'example-02', - meta: { bucketSize: 10 }, - color: 'rgb(147, 0, 0)', - timeseries: { buckets: [] }, - SIBAGG: { value: 2 }, - }, - ]); + + test('should return a splits with no color', () => { + const series = { + id: 'SERIES', + color: '#F00', + split_mode: 'terms', + terms_field: 'beat.hostname', + terms_size: 10, + metrics: [ + { id: 'AVG', type: 'avg', field: 'cpu' }, + { id: 'SIBAGG', type: 'avg_bucket', field: 'AVG' }, + ], + }; + const panel = { type: 'timeseries' }; + expect(getSplits(resp, panel, series)).toEqual([ + { + id: 'SERIES:example-01', + key: 'example-01', + label: 'example-01', + meta: { bucketSize: 10 }, + color: undefined, + timeseries: { buckets: [] }, + SIBAGG: { value: 1 }, + }, + { + id: 'SERIES:example-02', + key: 'example-02', + label: 'example-02', + meta: { bucketSize: 10 }, + color: undefined, + timeseries: { buckets: [] }, + SIBAGG: { value: 2 }, + }, + ]); + }); + + test('should return gradient color', () => { + const series = { + id: 'SERIES', + color: '#F00', + split_mode: 'terms', + split_color_mode: 'gradient', + terms_field: 'beat.hostname', + terms_size: 10, + metrics: [ + { id: 'AVG', type: 'avg', field: 'cpu' }, + { id: 'SIBAGG', type: 'avg_bucket', field: 'AVG' }, + ], + }; + const panel = { type: 'timeseries' }; + expect(getSplits(resp, panel, series)).toEqual([ + expect.objectContaining({ + color: 'rgb(255, 0, 0)', + }), + expect.objectContaining({ + color: 'rgb(147, 0, 0)', + }), + ]); + }); + + test('should return rainbow color', () => { + const series = { + id: 'SERIES', + color: '#F00', + split_mode: 'terms', + split_color_mode: 'rainbow', + terms_field: 'beat.hostname', + terms_size: 10, + metrics: [ + { id: 'AVG', type: 'avg', field: 'cpu' }, + { id: 'SIBAGG', type: 'avg_bucket', field: 'AVG' }, + ], + }; + const panel = { type: 'timeseries' }; + expect(getSplits(resp, panel, series)).toEqual([ + expect.objectContaining({ + color: '#68BC00', + }), + expect.objectContaining({ + color: '#009CE0', + }), + ]); + }); }); test('should return a splits for filters group bys', () => { diff --git a/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts b/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts index 26f8278cd3d43..83d53d27e41fd 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization_migrations.test.ts @@ -1460,4 +1460,62 @@ describe('migration visualization', () => { expect(migratedParams.gauge_color_rules[1]).toEqual(params.gauge_color_rules[1]); }); }); + + describe('7.8.0 tsvb split_color_mode', () => { + const migrate = (doc: any) => + visualizationSavedObjectTypeMigrations['7.8.0']( + doc as Parameters[0], + savedObjectMigrationContext + ); + + const generateDoc = (params: any) => ({ + attributes: { + title: 'My Vis', + type: 'visualization', + description: 'This is my super cool vis.', + visState: JSON.stringify(params), + uiStateJSON: '{}', + version: 1, + kibanaSavedObjectMeta: { + searchSourceJSON: '{}', + }, + }, + }); + + it('should change a missing split_color_mode to gradient', () => { + const params = { type: 'metrics', params: { series: [{}] } }; + const testDoc1 = generateDoc(params); + const migratedTestDoc1 = migrate(testDoc1); + const series = JSON.parse(migratedTestDoc1.attributes.visState).params.series; + + expect(series[0].split_color_mode).toEqual('gradient'); + }); + + it('should not change the color mode if it is set', () => { + const params = { type: 'metrics', params: { series: [{ split_color_mode: 'gradient' }] } }; + const testDoc1 = generateDoc(params); + const migratedTestDoc1 = migrate(testDoc1); + const series = JSON.parse(migratedTestDoc1.attributes.visState).params.series; + + expect(series[0].split_color_mode).toEqual('gradient'); + }); + + it('should not change the color mode if it is non-default', () => { + const params = { type: 'metrics', params: { series: [{ split_color_mode: 'rainbow' }] } }; + const testDoc1 = generateDoc(params); + const migratedTestDoc1 = migrate(testDoc1); + const series = JSON.parse(migratedTestDoc1.attributes.visState).params.series; + + expect(series[0].split_color_mode).toEqual('rainbow'); + }); + + it('should not migrate a visualization of unknown type', () => { + const params = { type: 'unknown', params: { series: [{}] } }; + const doc = generateDoc(params); + const migratedDoc = migrate(doc); + const series = JSON.parse(migratedDoc.attributes.visState).params.series; + + expect(series[0].split_color_mode).toBeUndefined(); + }); + }); }); diff --git a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts index 80783e41863ea..94473e35a942d 100644 --- a/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts +++ b/src/plugins/visualizations/server/saved_objects/visualization_migrations.ts @@ -602,7 +602,39 @@ const migrateMatchAllQuery: SavedObjectMigrationFn = doc => { }; } } + return doc; +}; + +// [TSVB] Default color palette is changing, keep the default for older viz +const migrateTsvbDefaultColorPalettes: SavedObjectMigrationFn = doc => { + const visStateJSON = get(doc, 'attributes.visState'); + let visState; + + if (visStateJSON) { + try { + visState = JSON.parse(visStateJSON); + } catch (e) { + // Let it go, the data is invalid and we'll leave it as is + } + if (visState && visState.type === 'metrics') { + const series: any[] = get(visState, 'params.series') || []; + series.forEach(part => { + // The default value was not saved before + if (!part.split_color_mode) { + part.split_color_mode = 'gradient'; + } + }); + + return { + ...doc, + attributes: { + ...doc.attributes, + visState: JSON.stringify(visState), + }, + }; + } + } return doc; }; @@ -639,4 +671,5 @@ export const visualizationSavedObjectTypeMigrations = { '7.3.1': flow(migrateFiltersAggQueryStringQueries), '7.4.2': flow(transformSplitFiltersStringToQueryObject), '7.7.0': flow(migrateOperatorKeyTypo), + '7.8.0': flow(migrateTsvbDefaultColorPalettes), }; diff --git a/test/functional/apps/visualize/_tsvb_time_series.ts b/test/functional/apps/visualize/_tsvb_time_series.ts index fa79190a5bf94..ac89c2b55e514 100644 --- a/test/functional/apps/visualize/_tsvb_time_series.ts +++ b/test/functional/apps/visualize/_tsvb_time_series.ts @@ -25,7 +25,6 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { const retry = getService('retry'); const log = getService('log'); const kibanaServer = getService('kibanaServer'); - const testSubjects = getService('testSubjects'); describe('visual builder', function describeIndexTests() { beforeEach(async () => { @@ -126,20 +125,18 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { expect(actualCountMin).to.be('3 hours'); }); - // --reversed class is not implemented in @elastic\chart - describe.skip('Dark mode', () => { + describe('Dark mode', () => { before(async () => { await kibanaServer.uiSettings.update({ 'theme:darkMode': true, }); }); - it(`viz should have 'reversed' class when background color is white`, async () => { + it(`viz should have light class when background color is white`, async () => { await visualBuilder.clickPanelOptions('timeSeries'); await visualBuilder.setBackgroundColor('#FFFFFF'); - const classNames = await testSubjects.getAttribute('timeseriesChart', 'class'); - expect(classNames.includes('tvbVisTimeSeries--reversed')).to.be(true); + expect(await visualBuilder.checkTimeSeriesIsLight()).to.be(true); }); after(async () => { diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index b8e6c812b46bd..12962b3a5cdef 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -71,6 +71,10 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro } } + public async checkTimeSeriesIsLight() { + return await find.existsByCssSelector('.tvbVisTimeSeriesLight'); + } + public async checkTimeSeriesLegendIsPresent() { const isPresent = await find.existsByCssSelector('.echLegend'); if (!isPresent) { From 635be640d54488d5a6e2de1e3dea1a32a637dcfa Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 20 Apr 2020 10:50:54 -0600 Subject: [PATCH 13/17] [Maps] fix date labels (#63909) * [Maps] fix date labels * review feedback Co-authored-by: Elastic Machine --- .../maps/public/elasticsearch_geo_utils.js | 12 +++++++- .../public/elasticsearch_geo_utils.test.js | 29 +++++++++++++++---- .../es_search_source/es_search_source.js | 12 +++++++- .../properties/dynamic_style_property.js | 4 +++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/maps/public/elasticsearch_geo_utils.js b/x-pack/plugins/maps/public/elasticsearch_geo_utils.js index 617cf537fd5c3..417c5d84f8916 100644 --- a/x-pack/plugins/maps/public/elasticsearch_geo_utils.js +++ b/x-pack/plugins/maps/public/elasticsearch_geo_utils.js @@ -64,7 +64,7 @@ function ensureGeometryType(type, expectedTypes) { * @param {string} geoFieldType Geometry field type ["geo_point", "geo_shape"] * @returns {number} */ -export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType) { +export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType, epochMillisFields) { const features = []; const tmpGeometriesAccumulator = []; @@ -80,6 +80,16 @@ export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType) { geoShapeToGeometry(properties[geoFieldName], tmpGeometriesAccumulator); } + // There is a bug in Elasticsearch API where epoch_millis are returned as a string instead of a number + // https://github.com/elastic/elasticsearch/issues/50622 + // Convert these field values to integers. + for (let i = 0; i < epochMillisFields.length; i++) { + const fieldName = epochMillisFields[i]; + if (typeof properties[fieldName] === 'string') { + properties[fieldName] = parseInt(properties[fieldName]); + } + } + // don't include geometry field value in properties delete properties[geoFieldName]; diff --git a/x-pack/plugins/maps/public/elasticsearch_geo_utils.test.js b/x-pack/plugins/maps/public/elasticsearch_geo_utils.test.js index 5db7556be4639..fc02e19173843 100644 --- a/x-pack/plugins/maps/public/elasticsearch_geo_utils.test.js +++ b/x-pack/plugins/maps/public/elasticsearch_geo_utils.test.js @@ -66,7 +66,7 @@ describe('hitsToGeoJson', () => { }, }, ]; - const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point'); + const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point', []); expect(geojson.type).toBe('FeatureCollection'); expect(geojson.features.length).toBe(2); expect(geojson.features[0]).toEqual({ @@ -94,7 +94,7 @@ describe('hitsToGeoJson', () => { _source: {}, }, ]; - const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point'); + const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point', []); expect(geojson.type).toBe('FeatureCollection'); expect(geojson.features.length).toBe(1); }); @@ -111,7 +111,7 @@ describe('hitsToGeoJson', () => { }, }, ]; - const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point'); + const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point', []); expect(geojson.features.length).toBe(1); const feature = geojson.features[0]; expect(feature.properties.myField).toBe(8); @@ -128,7 +128,7 @@ describe('hitsToGeoJson', () => { }, }, ]; - const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point'); + const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point', []); expect(geojson.type).toBe('FeatureCollection'); expect(geojson.features.length).toBe(2); expect(geojson.features[0]).toEqual({ @@ -159,6 +159,23 @@ describe('hitsToGeoJson', () => { }); }); + it('Should convert epoch_millis value from string to integer', () => { + const hits = [ + { + _id: 'doc1', + _index: 'index1', + _source: { + [geoFieldName]: '20,100', + myDateField: '1587156257081', + }, + }, + ]; + const geojson = hitsToGeoJson(hits, flattenHitMock, geoFieldName, 'geo_point', ['myDateField']); + expect(geojson.type).toBe('FeatureCollection'); + expect(geojson.features.length).toBe(1); + expect(geojson.features[0].properties.myDateField).toBe(1587156257081); + }); + describe('dot in geoFieldName', () => { const indexPatternMock = { fields: { @@ -184,7 +201,7 @@ describe('hitsToGeoJson', () => { }, }, ]; - const geojson = hitsToGeoJson(hits, indexPatternFlattenHit, 'my.location', 'geo_point'); + const geojson = hitsToGeoJson(hits, indexPatternFlattenHit, 'my.location', 'geo_point', []); expect(geojson.features[0].geometry).toEqual({ coordinates: [100, 20], type: 'Point', @@ -199,7 +216,7 @@ describe('hitsToGeoJson', () => { }, }, ]; - const geojson = hitsToGeoJson(hits, indexPatternFlattenHit, 'my.location', 'geo_point'); + const geojson = hitsToGeoJson(hits, indexPatternFlattenHit, 'my.location', 'geo_point', []); expect(geojson.features[0].geometry).toEqual({ coordinates: [100, 20], type: 'Point', diff --git a/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.js b/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.js index 96679f0e85941..34fed37933e13 100644 --- a/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.js +++ b/x-pack/plugins/maps/public/layers/sources/es_search_source/es_search_source.js @@ -387,11 +387,21 @@ export class ESSearchSource extends AbstractESSource { }); return properties; }; + const epochMillisFields = searchFilters.fieldNames.filter(fieldName => { + const field = getField(indexPattern, fieldName); + return field.readFromDocValues && field.type === 'date'; + }); let featureCollection; try { const geoField = await this._getGeoField(); - featureCollection = hitsToGeoJson(hits, flattenHit, geoField.name, geoField.type); + featureCollection = hitsToGeoJson( + hits, + flattenHit, + geoField.name, + geoField.type, + epochMillisFields + ); } catch (error) { throw new Error( i18n.translate('xpack.maps.source.esSearch.convertToGeoJsonErrorMsg', { diff --git a/x-pack/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js b/x-pack/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js index ea521f8749d80..8cef78f9a8f21 100644 --- a/x-pack/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js +++ b/x-pack/plugins/maps/public/layers/styles/vector/properties/dynamic_style_property.js @@ -279,6 +279,10 @@ export class DynamicStyleProperty extends AbstractStyleProperty { } getNumericalMbFeatureStateValue(value) { + if (typeof value === 'number') { + return value; + } + const valueAsFloat = parseFloat(value); return isNaN(valueAsFloat) ? null : valueAsFloat; } From 96b3fd1fe32b0fe6bb682573f368b5ba265f358f Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Mon, 20 Apr 2020 11:04:57 -0700 Subject: [PATCH 14/17] [Metrics UI] Remove remaining field filtering (#63398) Co-authored-by: Elastic Machine --- .../components/metrics_explorer/group_by.tsx | 15 +-------------- .../components/metrics_explorer/kuery_bar.tsx | 3 +-- .../components/metrics_explorer/metrics.tsx | 5 +---- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/infra/public/components/metrics_explorer/group_by.tsx b/x-pack/plugins/infra/public/components/metrics_explorer/group_by.tsx index 750894fd0188b..3246a2aa4a731 100644 --- a/x-pack/plugins/infra/public/components/metrics_explorer/group_by.tsx +++ b/x-pack/plugins/infra/public/components/metrics_explorer/group_by.tsx @@ -10,7 +10,6 @@ import { i18n } from '@kbn/i18n'; import React, { useCallback } from 'react'; import { IFieldType } from 'src/plugins/data/public'; import { MetricsExplorerOptions } from '../../containers/metrics_explorer/use_metrics_explorer_options'; -import { isDisplayable } from '../../utils/is_displayable'; interface Props { options: MetricsExplorerOptions; @@ -27,18 +26,6 @@ export const MetricsExplorerGroupBy = ({ options, onChange, fields }: Props) => [onChange] ); - const metricPrefixes = options.metrics - .map( - metric => - (metric.field && - metric.field - .split(/\./) - .slice(0, 2) - .join('.')) || - null - ) - .filter(metric => metric) as string[]; - return ( singleSelection={true} selectedOptions={(options.groupBy && [{ label: options.groupBy }]) || []} options={fields - .filter(f => isDisplayable(f, metricPrefixes) && f.aggregatable && f.type === 'string') + .filter(f => f.aggregatable && f.type === 'string') .map(f => ({ label: f.name }))} onChange={handleChange} isClearable={true} diff --git a/x-pack/plugins/infra/public/components/metrics_explorer/kuery_bar.tsx b/x-pack/plugins/infra/public/components/metrics_explorer/kuery_bar.tsx index dcc160d05b6ad..7c3e0444dbeea 100644 --- a/x-pack/plugins/infra/public/components/metrics_explorer/kuery_bar.tsx +++ b/x-pack/plugins/infra/public/components/metrics_explorer/kuery_bar.tsx @@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n'; import React, { useEffect, useState } from 'react'; import { WithKueryAutocompletion } from '../../containers/with_kuery_autocompletion'; import { AutocompleteField } from '../autocomplete_field'; -import { isDisplayable } from '../../utils/is_displayable'; import { esKuery, IIndexPattern } from '../../../../../../src/plugins/data/public'; interface Props { @@ -51,7 +50,7 @@ export const MetricsExplorerKueryBar = ({ const filteredDerivedIndexPattern = { ...derivedIndexPattern, - fields: derivedIndexPattern.fields.filter(field => isDisplayable(field)), + fields: derivedIndexPattern.fields, }; const defaultPlaceholder = i18n.translate( diff --git a/x-pack/plugins/infra/public/components/metrics_explorer/metrics.tsx b/x-pack/plugins/infra/public/components/metrics_explorer/metrics.tsx index 79d4122733c55..a49e42c9cac0e 100644 --- a/x-pack/plugins/infra/public/components/metrics_explorer/metrics.tsx +++ b/x-pack/plugins/infra/public/components/metrics_explorer/metrics.tsx @@ -12,7 +12,6 @@ import { IFieldType } from 'src/plugins/data/public'; import { colorTransformer, MetricsExplorerColor } from '../../../common/color_palette'; import { MetricsExplorerMetric } from '../../../common/http_api/metrics_explorer'; import { MetricsExplorerOptions } from '../../containers/metrics_explorer/use_metrics_explorer_options'; -import { isDisplayable } from '../../utils/is_displayable'; interface Props { autoFocus?: boolean; @@ -54,9 +53,7 @@ export const MetricsExplorerMetrics = ({ options, onChange, fields, autoFocus = [onChange, options.aggregation, colors] ); - const comboOptions = fields - .filter(field => isDisplayable(field)) - .map(field => ({ label: field.name, value: field.name })); + const comboOptions = fields.map(field => ({ label: field.name, value: field.name })); const selectedOptions = options.metrics .filter(m => m.aggregation !== 'count') .map(metric => ({ From 86922e80a8a1d96c23d174031d8d07371ea78b39 Mon Sep 17 00:00:00 2001 From: Joel Griffith Date: Mon, 20 Apr 2020 11:23:16 -0700 Subject: [PATCH 15/17] [Reporting] Config flag to escape formula CSV values (#63645) * Adds a new xpack.reporting.csv.escapeFormulaValues boolean to auto-escape potentially bad cells * Treat csvs with formulas differently than those that aren't escaped Co-authored-by: Elastic Machine --- .../resources/bin/kibana-docker | 1 + .../plugins/reporting/common/constants.ts | 1 + .../csv/server/execute_job.test.ts | 74 ++++++++++++++++++- .../export_types/csv/server/execute_job.ts | 5 +- .../csv/server/lib/cell_has_formula.ts | 11 +++ .../server/lib/check_cells_for_formulas.ts | 7 +- .../csv/server/lib/escape_value.test.ts | 34 ++++++++- .../csv/server/lib/escape_value.ts | 11 ++- .../csv/server/lib/generate_csv.ts | 17 ++++- .../reporting/export_types/csv/types.d.ts | 2 + .../server/lib/generate_csv_search.ts | 1 + .../plugins/reporting/server/config/schema.ts | 1 + 12 files changed, 152 insertions(+), 13 deletions(-) create mode 100644 x-pack/legacy/plugins/reporting/export_types/csv/server/lib/cell_has_formula.ts diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker index d4d2e86e1e96b..38acfb15d3ece 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker @@ -195,6 +195,7 @@ kibana_vars=( xpack.reporting.capture.viewport.width xpack.reporting.capture.zoom xpack.reporting.csv.checkForFormulas + xpack.reporting.csv.escapeFormulaValues xpack.reporting.csv.enablePanelActionDownload xpack.reporting.csv.maxSizeBytes xpack.reporting.csv.scroll.duration diff --git a/x-pack/legacy/plugins/reporting/common/constants.ts b/x-pack/legacy/plugins/reporting/common/constants.ts index e3d6a4274e7df..f30a7cc87f318 100644 --- a/x-pack/legacy/plugins/reporting/common/constants.ts +++ b/x-pack/legacy/plugins/reporting/common/constants.ts @@ -20,6 +20,7 @@ export const API_GENERATE_IMMEDIATE = `${API_BASE_URL_V1}/generate/immediate/csv export const CONTENT_TYPE_CSV = 'text/csv'; export const CSV_REPORTING_ACTION = 'downloadCsvReport'; export const CSV_BOM_CHARS = '\ufeff'; +export const CSV_FORMULA_CHARS = ['=', '+', '-', '@']; export const WHITELISTED_JOB_CONTENT_TYPES = [ 'application/json', diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts index f0afade8629ab..ad35aaf003094 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.test.ts @@ -300,7 +300,7 @@ describe('CSV Execute Job', function() { }); }); - describe('Cells with formula values', () => { + describe('Warning when cells have formulas', () => { it('returns `csv_contains_formulas` when cells contain formulas', async function() { configGetStub.withArgs('csv', 'checkForFormulas').returns(true); callAsCurrentUserStub.onFirstCall().returns({ @@ -353,6 +353,7 @@ describe('CSV Execute Job', function() { it('returns no warnings when cells have no formulas', async function() { configGetStub.withArgs('csv', 'checkForFormulas').returns(true); + configGetStub.withArgs('csv', 'escapeFormulaValues').returns(false); callAsCurrentUserStub.onFirstCall().returns({ hits: { hits: [{ _source: { one: 'foo', two: 'bar' } }], @@ -376,6 +377,33 @@ describe('CSV Execute Job', function() { expect(csvContainsFormulas).toEqual(false); }); + it('returns no warnings when cells have formulas but are escaped', async function() { + configGetStub.withArgs('csv', 'checkForFormulas').returns(true); + configGetStub.withArgs('csv', 'escapeFormulaValues').returns(true); + callAsCurrentUserStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { '=SUM(A1:A2)': 'foo', two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); + const jobParams = getJobDocPayload({ + headers: encryptedHeaders, + fields: ['=SUM(A1:A2)', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }); + + const { csv_contains_formulas: csvContainsFormulas } = await executeJob( + 'job123', + jobParams, + cancellationToken + ); + + expect(csvContainsFormulas).toEqual(false); + }); + it('returns no warnings when configured not to', async () => { configGetStub.withArgs('csv', 'checkForFormulas').returns(false); callAsCurrentUserStub.onFirstCall().returns({ @@ -446,6 +474,50 @@ describe('CSV Execute Job', function() { }); }); + describe('Escaping cells with formulas', () => { + it('escapes values with formulas', async () => { + configGetStub.withArgs('csv', 'escapeFormulaValues').returns(true); + callAsCurrentUserStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: `=cmd|' /C calc'!A0`, two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); + const jobParams = getJobDocPayload({ + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }); + const { content } = await executeJob('job123', jobParams, cancellationToken); + + expect(content).toEqual("one,two\n\"'=cmd|' /C calc'!A0\",bar\n"); + }); + + it('does not escapes values with formulas', async () => { + configGetStub.withArgs('csv', 'escapeFormulaValues').returns(false); + callAsCurrentUserStub.onFirstCall().returns({ + hits: { + hits: [{ _source: { one: `=cmd|' /C calc'!A0`, two: 'bar' } }], + }, + _scroll_id: 'scrollId', + }); + + const executeJob = await executeJobFactory(mockReportingPlugin, mockLogger); + const jobParams = getJobDocPayload({ + headers: encryptedHeaders, + fields: ['one', 'two'], + conflictedTypesFields: [], + searchRequest: { index: null, body: null }, + }); + const { content } = await executeJob('job123', jobParams, cancellationToken); + + expect(content).toEqual('one,two\n"=cmd|\' /C calc\'!A0",bar\n'); + }); + }); + describe('Elasticsearch call errors', function() { it('should reject Promise if search call errors out', async function() { callAsCurrentUserStub.rejects(new Error()); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts index 376a398da274f..dbe305bc452db 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/execute_job.ts @@ -123,7 +123,7 @@ export const executeJobFactory: ExecuteJobFactory + CSV_FORMULA_CHARS.some(formulaChar => startsWith(val, formulaChar)); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.ts index 09f7cd2061ffb..0ec39c527d656 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/check_cells_for_formulas.ts @@ -5,8 +5,7 @@ */ import * as _ from 'lodash'; - -const formulaValues = ['=', '+', '-', '@']; +import { cellHasFormulas } from './cell_has_formula'; interface IFlattened { [header: string]: string; @@ -14,7 +13,7 @@ interface IFlattened { export const checkIfRowsHaveFormulas = (flattened: IFlattened, fields: string[]) => { const pruned = _.pick(flattened, fields); - const csvValues = [..._.keys(pruned), ...(_.values(pruned) as string[])]; + const cells = [..._.keys(pruned), ...(_.values(pruned) as string[])]; - return _.some(csvValues, cell => _.some(formulaValues, char => _.startsWith(cell, char))); + return _.some(cells, cell => cellHasFormulas(cell)); }; diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts index 64b021a2aeea8..dd0f9d08b864b 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.test.ts @@ -11,7 +11,7 @@ describe('escapeValue', function() { describe('quoteValues is true', function() { let escapeValue: (val: string) => string; beforeEach(function() { - escapeValue = createEscapeValue(true); + escapeValue = createEscapeValue(true, false); }); it('should escape value with spaces', function() { @@ -46,7 +46,7 @@ describe('escapeValue', function() { describe('quoteValues is false', function() { let escapeValue: (val: string) => string; beforeEach(function() { - escapeValue = createEscapeValue(false); + escapeValue = createEscapeValue(false, false); }); it('should return the value unescaped', function() { @@ -54,4 +54,34 @@ describe('escapeValue', function() { expect(escapeValue(value)).to.be(value); }); }); + + describe('escapeValues', () => { + describe('when true', () => { + let escapeValue: (val: string) => string; + beforeEach(function() { + escapeValue = createEscapeValue(true, true); + }); + + ['@', '+', '-', '='].forEach(badChar => { + it(`should escape ${badChar} injection values`, function() { + expect(escapeValue(`${badChar}cmd|' /C calc'!A0`)).to.be( + `"'${badChar}cmd|' /C calc'!A0"` + ); + }); + }); + }); + + describe('when false', () => { + let escapeValue: (val: string) => string; + beforeEach(function() { + escapeValue = createEscapeValue(true, false); + }); + + ['@', '+', '-', '='].forEach(badChar => { + it(`should not escape ${badChar} injection values`, function() { + expect(escapeValue(`${badChar}cmd|' /C calc'!A0`)).to.be(`"${badChar}cmd|' /C calc'!A0"`); + }); + }); + }); + }); }); diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts index 563de563350e9..60e75d74b2f98 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/escape_value.ts @@ -5,15 +5,20 @@ */ import { RawValue } from './types'; +import { cellHasFormulas } from './cell_has_formula'; const nonAlphaNumRE = /[^a-zA-Z0-9]/; const allDoubleQuoteRE = /"/g; -export function createEscapeValue(quoteValues: boolean): (val: RawValue) => string { +export function createEscapeValue( + quoteValues: boolean, + escapeFormulas: boolean +): (val: RawValue) => string { return function escapeValue(val: RawValue) { if (val && typeof val === 'string') { - if (quoteValues && nonAlphaNumRE.test(val)) { - return `"${val.replace(allDoubleQuoteRE, '""')}"`; + const formulasEscaped = escapeFormulas && cellHasFormulas(val) ? "'" + val : val; + if (quoteValues && nonAlphaNumRE.test(formulasEscaped)) { + return `"${formulasEscaped.replace(allDoubleQuoteRE, '""')}"`; } } diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts index 1986e68917ba8..c7996ebf832a1 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/server/lib/generate_csv.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import { Logger } from '../../../../types'; import { GenerateCsvParams, SavedSearchGeneratorResult } from '../../types'; import { createFlattenHit } from './flatten_hit'; @@ -26,14 +27,17 @@ export function createGenerateCsv(logger: Logger) { cancellationToken, settings, }: GenerateCsvParams): Promise { - const escapeValue = createEscapeValue(settings.quoteValues); + const escapeValue = createEscapeValue(settings.quoteValues, settings.escapeFormulaValues); const builder = new MaxSizeStringBuilder(settings.maxSizeBytes); const header = `${fields.map(escapeValue).join(settings.separator)}\n`; + const warnings: string[] = []; + if (!builder.tryAppend(header)) { return { size: 0, content: '', maxSizeReached: true, + warnings: [], }; } @@ -82,11 +86,20 @@ export function createGenerateCsv(logger: Logger) { const size = builder.getSizeInBytes(); logger.debug(`finished generating, total size in bytes: ${size}`); + if (csvContainsFormulas && settings.escapeFormulaValues) { + warnings.push( + i18n.translate('xpack.reporting.exportTypes.csv.generateCsv.escapedFormulaValues', { + defaultMessage: 'CSV may contain formulas whose values have been escaped', + }) + ); + } + return { content: builder.getString(), - csvContainsFormulas, + csvContainsFormulas: csvContainsFormulas && !settings.escapeFormulaValues, maxSizeReached, size, + warnings, }; }; } diff --git a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts index 529c195486bc6..40a42db352635 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv/types.d.ts @@ -87,6 +87,7 @@ export interface SavedSearchGeneratorResult { size: number; maxSizeReached: boolean; csvContainsFormulas?: boolean; + warnings: string[]; } export interface CsvResultFromSearch { @@ -109,5 +110,6 @@ export interface GenerateCsvParams { maxSizeBytes: number; scroll: ScrollConfig; checkForFormulas?: boolean; + escapeFormulaValues: boolean; }; } diff --git a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts index 9757c71c19cf4..2611b74c83de9 100644 --- a/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts +++ b/x-pack/legacy/plugins/reporting/export_types/csv_from_savedobject/server/lib/generate_csv_search.ts @@ -173,6 +173,7 @@ export async function generateCsvSearch( ...uiSettings, maxSizeBytes: config.get('csv', 'maxSizeBytes'), scroll: config.get('csv', 'scroll'), + escapeFormulaValues: config.get('csv', 'escapeFormulaValues'), timezone, }, }; diff --git a/x-pack/plugins/reporting/server/config/schema.ts b/x-pack/plugins/reporting/server/config/schema.ts index 67d70c1513c15..402fddcb5e014 100644 --- a/x-pack/plugins/reporting/server/config/schema.ts +++ b/x-pack/plugins/reporting/server/config/schema.ts @@ -114,6 +114,7 @@ const CaptureSchema = schema.object({ const CsvSchema = schema.object({ checkForFormulas: schema.boolean({ defaultValue: true }), + escapeFormulaValues: schema.boolean({ defaultValue: false }), enablePanelActionDownload: schema.boolean({ defaultValue: true }), maxSizeBytes: schema.number({ defaultValue: 1024 * 1024 * 10, // 10MB From d69b1a0e39796fcf1131369168176ff76438ed77 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Mon, 20 Apr 2020 20:36:09 +0200 Subject: [PATCH 16/17] [Discover] Allow user to generate a report after saving a modified saved search (#63623) * Fix missing reset of initial state when saving saved searches * Fix invalid setting of docTitle * Add functional test --- .../discover/np_ready/angular/discover.js | 6 ++++-- x-pack/test/reporting/functional/reporting.js | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index 72276a38f6ac2..56966d6294c9a 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -57,7 +57,6 @@ const { core, chrome, data, - docTitle, history, indexPatterns, filterManager, @@ -214,6 +213,7 @@ function discoverController( isAppStateDirty, kbnUrlStateStorage, getPreviousAppState, + resetInitialAppState, } = getState({ defaultAppState: getStateDefaults(), storeInSessionStorage: config.get('state:storeInSessionStorage'), @@ -373,6 +373,8 @@ function discoverController( // If the save wasn't successful, put the original values back. if (!response.id || response.error) { savedSearch.title = currentTitle; + } else { + resetInitialAppState(); } return response; }); @@ -758,7 +760,7 @@ function discoverController( } else { // Update defaults so that "reload saved query" functions correctly setAppState(getStateDefaults()); - docTitle.change(savedSearch.lastSavedTitle); + chrome.docTitle.change(savedSearch.lastSavedTitle); } } }); diff --git a/x-pack/test/reporting/functional/reporting.js b/x-pack/test/reporting/functional/reporting.js index 6107363986a40..c1a2ae634662c 100644 --- a/x-pack/test/reporting/functional/reporting.js +++ b/x-pack/test/reporting/functional/reporting.js @@ -24,6 +24,7 @@ export default function({ getService, getPageObjects }) { const browser = getService('browser'); const log = getService('log'); const config = getService('config'); + const filterBar = getService('filterBar'); const PageObjects = getPageObjects([ 'reporting', 'common', @@ -161,7 +162,27 @@ export default function({ getService, getPageObjects }) { expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); }); + it('becomes available/not available when a saved search is created, changed and saved again', async () => { + // create new search, csv export is not available + await PageObjects.discover.clickNewSearchButton(); + await PageObjects.reporting.openCsvReportingPanel(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); + // save search, csv export is available + await PageObjects.discover.saveSearch('my search - expectEnabledGenerateReportButton 2'); + await PageObjects.reporting.openCsvReportingPanel(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); + // add filter, csv export is not available + await filterBar.addFilter('currency', 'is', 'EUR'); + await PageObjects.reporting.openCsvReportingPanel(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be('true'); + // save search again, csv export is available + await PageObjects.discover.saveSearch('my search - expectEnabledGenerateReportButton 2'); + await PageObjects.reporting.openCsvReportingPanel(); + expect(await PageObjects.reporting.isGenerateReportButtonDisabled()).to.be(null); + }); + it('generates a report with data', async () => { + await PageObjects.discover.clickNewSearchButton(); await PageObjects.reporting.setTimepickerInDataRange(); await PageObjects.discover.saveSearch('my search - with data - expectReportCanBeCreated'); await PageObjects.reporting.openCsvReportingPanel(); From 53a07528414495da59673c47ad80d3d5f777f2dd Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Mon, 20 Apr 2020 19:37:26 +0100 Subject: [PATCH 17/17] [ML] Fixing single metric viewer page padding (#63839) Co-authored-by: Elastic Machine --- .../public/application/timeseriesexplorer/timeseriesexplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js index 5e505757dd2aa..42742f6efcb2a 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js @@ -150,7 +150,7 @@ function getTimeseriesexplorerDefaultState() { }; } -const containerPadding = 24; +const containerPadding = 34; export class TimeSeriesExplorer extends React.Component { static propTypes = {