From c4e9b5ad6f9ecb1c04daefa41cf9fdce17a6e03e Mon Sep 17 00:00:00 2001 From: Ashwin P Chandran Date: Wed, 13 Sep 2023 17:56:52 -0700 Subject: [PATCH] Basic working version of OSD without angular (#4982) Signed-off-by: Ashwin P Chandran --- package.json | 12 +- .../__snapshots__/directive.test.ts.snap | 69 - .../osd-i18n/src/angular/directive.test.ts | 172 --- packages/osd-i18n/src/angular/directive.ts | 126 -- packages/osd-i18n/src/angular/filter.test.ts | 68 - packages/osd-i18n/src/angular/filter.ts | 42 - packages/osd-i18n/src/angular/index.ts | 38 - .../osd-i18n/src/angular/provider.test.ts | 69 - packages/osd-i18n/src/angular/provider.ts | 48 - .../config/global_selectors.json | 4 +- .../local_nav/_local_date_picker.scss | 13 - packages/osd-ui-shared-deps/entry.js | 3 - packages/osd-ui-shared-deps/index.js | 2 - packages/osd-ui-shared-deps/package.json | 3 +- src/plugins/dashboard/public/plugin.tsx | 4 - src/plugins/discover/common/index.ts | 1 - .../components/top_nav/get_top_nav_links.tsx | 24 +- .../view_components/canvas/top_nav.tsx | 17 +- src/plugins/discover/public/index.ts | 1 - src/plugins/discover/public/plugin.ts | 74 +- src/plugins/discover/server/ui_settings.ts | 12 - src/plugins/discover_legacy/README.md | 1 - src/plugins/discover_legacy/common/index.ts | 41 - .../opensearch_dashboards.json | 27 - .../public/application/_discover.scss | 164 --- .../public/application/angular/_index.scss | 2 - .../public/application/angular/context.html | 9 - .../public/application/angular/context.js | 122 -- .../application/angular/context/NOTES.md | 95 -- .../application/angular/context/_index.scss | 8 - .../application/angular/context/api/_stubs.js | 112 -- .../application/angular/context/api/anchor.js | 71 - .../angular/context/api/anchor.test.js | 158 --- .../context/api/context.predecessors.test.js | 241 ---- .../context/api/context.successors.test.js | 245 ---- .../angular/context/api/context.ts | 137 -- .../context/api/utils/date_conversion.test.ts | 43 - .../context/api/utils/date_conversion.ts | 76 -- .../api/utils/fetch_hits_in_interval.ts | 107 -- .../context/api/utils/generate_intervals.ts | 66 - .../get_opensearch_query_search_after.ts | 58 - .../api/utils/get_opensearch_query_sort.ts | 49 - .../angular/context/api/utils/sorting.test.ts | 38 - .../angular/context/api/utils/sorting.ts | 63 - .../components/action_bar/_action_bar.scss | 10 - .../context/components/action_bar/_index.scss | 1 - .../components/action_bar/action_bar.test.tsx | 104 -- .../components/action_bar/action_bar.tsx | 182 --- .../action_bar/action_bar_directive.ts | 36 - .../action_bar/action_bar_warning.tsx | 84 -- .../context/components/action_bar/index.ts | 31 - .../helpers/call_after_bindings_workaround.js | 74 -- .../angular/context/query/actions.js | 203 --- .../angular/context/query/constants.js | 41 - .../angular/context/query/index.js | 33 - .../angular/context/query/state.js | 39 - .../context/query_parameters/actions.js | 86 -- .../context/query_parameters/actions.test.ts | 168 --- .../context/query_parameters/constants.ts | 35 - .../angular/context/query_parameters/index.js | 33 - .../angular/context/query_parameters/state.ts | 47 - .../application/angular/context_app.html | 55 - .../public/application/angular/context_app.js | 151 --- .../application/angular/context_state.test.ts | 204 --- .../application/angular/context_state.ts | 307 ----- .../__snapshots__/no_results.test.js.snap | 230 ---- .../angular/directives/_histogram.scss | 11 - .../angular/directives/_index.scss | 2 - .../angular/directives/_no_results.scss | 3 - .../angular/directives/debounce/debounce.js | 79 -- .../directives/debounce/debounce.test.ts | 148 --- .../angular/directives/debounce/index.js | 31 - .../angular/directives/fixed_scroll.js | 166 --- .../angular/directives/fixed_scroll.test.js | 274 ---- .../angular/directives/histogram.tsx | 362 ------ .../application/angular/directives/index.js | 42 - .../angular/directives/no_results.js | 225 ---- .../angular/directives/no_results.test.js | 76 -- .../angular/directives/render_complete.ts | 42 - .../angular/directives/uninitialized.tsx | 78 -- .../public/application/angular/discover.js | 1156 ----------------- .../application/angular/discover_legacy.html | 36 - .../angular/discover_state.test.ts | 116 -- .../application/angular/discover_state.ts | 256 ---- .../public/application/angular/doc.html | 8 - .../public/application/angular/doc.ts | 81 -- .../angular/doc_table/_doc_table.scss | 158 --- .../angular/doc_table/actions/columns.ts | 67 - .../angular/doc_table/components/_index.scss | 2 - .../doc_table/components/_table_header.scss | 17 - .../tool_bar_pager_buttons.test.tsx.snap | 30 - .../tool_bar_pager_text.test.tsx.snap | 10 - .../doc_table/components/pager/index.ts | 40 - .../pager/tool_bar_pager_buttons.test.tsx | 73 -- .../pager/tool_bar_pager_buttons.tsx | 74 -- .../pager/tool_bar_pager_text.test.tsx | 43 - .../components/pager/tool_bar_pager_text.tsx | 52 - .../doc_table/components/row_headers.test.js | 508 -------- .../doc_table/components/table_header.ts | 58 - .../__snapshots__/table_header.test.tsx.snap | 221 ---- .../components/table_header/helpers.tsx | 92 -- .../table_header/table_header.test.tsx | 214 --- .../components/table_header/table_header.tsx | 82 -- .../table_header/table_header_column.tsx | 205 --- .../angular/doc_table/components/table_row.ts | 238 ---- .../doc_table/components/table_row/_cell.scss | 34 - .../components/table_row/_details.scss | 23 - .../components/table_row/_index.scss | 3 - .../doc_table/components/table_row/_open.scss | 40 - .../doc_table/components/table_row/cell.html | 24 - .../components/table_row/details.html | 37 - .../doc_table/components/table_row/open.html | 7 - .../table_row/truncate_by_height.html | 3 - .../doc_table/create_doc_table_react.tsx | 142 -- .../angular/doc_table/doc_table.html | 67 - .../angular/doc_table/doc_table.test.js | 158 --- .../angular/doc_table/doc_table.ts | 113 -- .../angular/doc_table/doc_table_strings.js | 43 - .../application/angular/doc_table/index.scss | 2 - .../application/angular/doc_table/index.ts | 33 - .../angular/doc_table/infinite_scroll.ts | 79 -- .../angular/doc_table/lib/get_default_sort.ts | 49 - .../angular/doc_table/lib/get_sort.test.ts | 107 -- .../angular/doc_table/lib/get_sort.ts | 92 -- .../lib/get_sort_for_search_source.ts | 65 - .../angular/doc_table/lib/pager/index.js | 32 - .../angular/doc_table/lib/pager/pager.js | 88 -- .../doc_table/lib/pager/pager_factory.ts | 40 - .../public/application/angular/doc_viewer.tsx | 59 - .../application/angular/doc_viewer_links.tsx | 28 - .../application/angular/helpers/index.ts | 31 - .../angular/helpers/point_series.ts | 122 -- .../public/application/angular/index.ts | 41 - .../public/application/angular/redirect.ts | 49 - .../application/angular/response_handler.js | 131 -- .../public/application/application.ts | 56 - .../context_error_message.test.tsx | 65 - .../context_error_message.tsx | 76 -- .../context_error_message_directive.ts | 38 - .../components/context_error_message/index.ts | 32 - .../create_discover_legacy_directive.ts | 67 - .../components/discover_legacy.tsx | 361 ----- .../application/components/doc/doc.test.tsx | 150 --- .../public/application/components/doc/doc.tsx | 140 -- .../doc/use_opensearch_doc_search.test.tsx | 98 -- .../doc/use_opensearch_doc_search.ts | 114 -- .../__snapshots__/doc_viewer.test.tsx.snap | 56 - .../doc_viewer_render_tab.test.tsx.snap | 20 - .../components/doc_viewer/doc_viewer.scss | 72 - .../components/doc_viewer/doc_viewer.test.tsx | 94 -- .../components/doc_viewer/doc_viewer.tsx | 75 -- .../doc_viewer/doc_viewer_render_error.tsx | 48 - .../doc_viewer/doc_viewer_render_tab.test.tsx | 52 - .../doc_viewer/doc_viewer_render_tab.tsx | 52 - .../components/doc_viewer/doc_viewer_tab.tsx | 101 -- .../doc_viewer_links.test.tsx.snap | 34 - .../doc_viewer_links.test.tsx | 68 - .../doc_viewer_links/doc_viewer_links.tsx | 35 - .../__snapshots__/field_name.test.tsx.snap | 94 -- .../components/field_name/field_name.test.tsx | 52 - .../components/field_name/field_name.tsx | 75 -- .../components/field_name/field_type_name.ts | 85 -- .../components/help_menu/help_menu_util.js | 47 - .../hits_counter/hits_counter.test.tsx | 80 -- .../components/hits_counter/hits_counter.tsx | 95 -- .../components/hits_counter/index.ts | 31 - .../json_code_block.test.tsx.snap | 20 - .../json_code_block/json_code_block.test.tsx | 46 - .../json_code_block/json_code_block.tsx | 45 - .../loading_spinner/loading_spinner.test.tsx | 45 - .../loading_spinner/loading_spinner.tsx | 47 - .../discover_index_pattern.test.tsx.snap | 3 - .../sidebar/change_indexpattern.tsx | 131 -- .../components/sidebar/discover_field.scss | 4 - .../sidebar/discover_field.test.tsx | 152 --- .../components/sidebar/discover_field.tsx | 245 ---- .../sidebar/discover_field_bucket.scss | 4 - .../sidebar/discover_field_bucket.tsx | 133 -- .../sidebar/discover_field_details.scss | 6 - .../sidebar/discover_field_details.test.tsx | 312 ----- .../sidebar/discover_field_details.tsx | 153 --- .../sidebar/discover_field_search.test.tsx | 160 --- .../sidebar/discover_field_search.tsx | 313 ----- .../sidebar/discover_index_pattern.test.tsx | 111 -- .../sidebar/discover_index_pattern.tsx | 104 -- .../sidebar/discover_index_pattern_title.tsx | 95 -- .../components/sidebar/discover_sidebar.scss | 99 -- .../sidebar/discover_sidebar.test.tsx | 148 --- .../components/sidebar/discover_sidebar.tsx | 326 ----- .../application/components/sidebar/index.ts | 31 - .../sidebar/lib/field_calculator.test.ts | 268 ---- .../sidebar/lib/field_calculator.ts | 148 --- .../sidebar/lib/field_filter.test.ts | 107 -- .../components/sidebar/lib/field_filter.ts | 89 -- .../components/sidebar/lib/get_details.ts | 71 - .../sidebar/lib/get_field_type_name.ts | 85 -- .../lib/get_index_pattern_field_list.ts | 53 - .../components/sidebar/lib/get_warnings.ts | 55 - .../sidebar/lib/group_fields.test.ts | 125 -- .../components/sidebar/lib/group_fields.tsx | 87 -- .../sidebar/lib/visualize_trigger_utils.ts | 122 -- .../sidebar/string_progress_bar.tsx | 46 - .../application/components/sidebar/types.ts | 52 - .../components/skip_bottom_button/index.ts | 31 - .../skip_bottom_button.test.tsx | 51 - .../skip_bottom_button/skip_bottom_button.tsx | 66 - .../components/table/table.test.tsx | 279 ---- .../application/components/table/table.tsx | 149 --- .../components/table/table_helper.test.ts | 58 - .../components/table/table_helper.tsx | 43 - .../components/table/table_row.tsx | 129 -- .../table/table_row_btn_collapse.tsx | 56 - .../table/table_row_btn_filter_add.tsx | 69 - .../table/table_row_btn_filter_exists.tsx | 81 -- .../table/table_row_btn_filter_remove.tsx | 69 - .../table/table_row_btn_toggle_column.tsx | 79 -- .../table/table_row_icon_no_mapping.tsx | 59 - .../table/table_row_icon_underscore.tsx | 63 - .../components/timechart_header/index.ts | 31 - .../timechart_header.test.tsx | 110 -- .../timechart_header/timechart_header.tsx | 183 --- .../open_search_panel.test.js.snap | 69 - .../components/top_nav/open_search_panel.js | 122 -- .../top_nav/open_search_panel.test.js | 48 - .../top_nav/show_open_search_panel.js | 57 - .../doc_views/doc_views_helpers.tsx | 105 -- .../doc_views/doc_views_registry.ts | 70 - .../application/doc_views/doc_views_types.ts | 86 -- .../doc_views_links_registry.ts | 18 - .../doc_views_links/doc_views_links_types.ts | 25 - .../application/embeddable/constants.ts | 31 - .../public/application/embeddable/index.ts | 33 - .../embeddable/search_embeddable.scss | 12 - .../embeddable/search_embeddable.ts | 361 ----- .../embeddable/search_embeddable_factory.ts | 131 -- .../embeddable/search_template.html | 20 - .../public/application/embeddable/types.ts | 62 - .../public/application/helpers/breadcrumbs.ts | 51 - .../helpers/format_number_with_commas.ts | 38 - .../helpers/get_index_pattern_id.ts | 71 - ...get_switch_index_pattern_app_state.test.ts | 101 -- .../get_switch_index_pattern_app_state.ts | 58 - .../public/application/helpers/index.ts | 32 - .../helpers/migrate_legacy_query.ts | 48 - .../helpers/popularize_field.test.ts | 93 -- .../application/helpers/popularize_field.ts | 52 - .../helpers/shorten_dotted_string.ts | 37 - .../helpers/validate_time_range.test.ts | 58 - .../helpers/validate_time_range.ts | 61 - .../public/application/index.scss | 2 - .../discover_legacy/public/build_services.ts | 129 -- .../public/get_inner_angular.ts | 208 --- src/plugins/discover_legacy/public/index.ts | 41 - src/plugins/discover_legacy/public/mocks.ts | 61 - .../public/opensearch_dashboards_services.ts | 129 -- src/plugins/discover_legacy/public/plugin.ts | 487 ------- .../public/saved_searches/_saved_search.ts | 86 -- .../public/saved_searches/index.ts | 32 - .../public/saved_searches/saved_searches.ts | 50 - .../public/saved_searches/types.ts | 47 - .../public/url_generator.test.ts | 269 ---- .../discover_legacy/public/url_generator.ts | 127 -- .../public/angular/angular_config.tsx | 380 ------ .../public/angular/index.ts | 38 - .../public/angular/osd_top_nav.js | 140 -- .../public/angular/promises.js | 140 -- .../angular/subscribe_with_scope.test.ts | 208 --- .../public/angular/subscribe_with_scope.ts | 96 -- .../public/angular/watch_multi.js | 159 --- .../angular_bootstrap/bind_html/bind_html.js | 28 - .../public/angular_bootstrap/index.ts | 61 - .../angular_bootstrap/tooltip/position.js | 178 --- .../angular_bootstrap/tooltip/tooltip.js | 434 ------- .../tooltip/tooltip_html_unsafe_popup.html | 4 - .../tooltip/tooltip_popup.html | 4 - .../public/index.ts | 2 - src/plugins/tile_map/public/plugin.ts | 2 +- yarn.lock | 49 - 278 files changed, 40 insertions(+), 25618 deletions(-) delete mode 100644 packages/osd-i18n/src/angular/__snapshots__/directive.test.ts.snap delete mode 100644 packages/osd-i18n/src/angular/directive.test.ts delete mode 100644 packages/osd-i18n/src/angular/directive.ts delete mode 100644 packages/osd-i18n/src/angular/filter.test.ts delete mode 100644 packages/osd-i18n/src/angular/filter.ts delete mode 100644 packages/osd-i18n/src/angular/index.ts delete mode 100644 packages/osd-i18n/src/angular/provider.test.ts delete mode 100644 packages/osd-i18n/src/angular/provider.ts delete mode 100644 src/plugins/discover_legacy/README.md delete mode 100644 src/plugins/discover_legacy/common/index.ts delete mode 100644 src/plugins/discover_legacy/opensearch_dashboards.json delete mode 100644 src/plugins/discover_legacy/public/application/_discover.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/_index.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/context.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/context.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/NOTES.md delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/_index.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/_stubs.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/anchor.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/anchor.test.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/context.predecessors.test.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/context.successors.test.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/context.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/utils/date_conversion.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/utils/date_conversion.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/utils/fetch_hits_in_interval.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/utils/generate_intervals.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/utils/get_opensearch_query_search_after.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/utils/get_opensearch_query_sort.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/utils/sorting.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/api/utils/sorting.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/components/action_bar/_action_bar.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/components/action_bar/_index.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar_directive.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar_warning.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/components/action_bar/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/helpers/call_after_bindings_workaround.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query/actions.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query/constants.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query/index.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query/state.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query_parameters/actions.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query_parameters/actions.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query_parameters/constants.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query_parameters/index.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context/query_parameters/state.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context_app.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/context_app.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/context_state.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/context_state.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/__snapshots__/no_results.test.js.snap delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/_histogram.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/_index.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/_no_results.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/debounce/debounce.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/debounce/debounce.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/debounce/index.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/fixed_scroll.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/fixed_scroll.test.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/histogram.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/index.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/no_results.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/no_results.test.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/render_complete.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/directives/uninitialized.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/discover.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/discover_legacy.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/discover_state.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/discover_state.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/_doc_table.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/actions/columns.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/_index.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/_table_header.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_buttons.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_text.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_text.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/row_headers.test.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header/helpers.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header/table_header.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header/table_header.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header/table_header_column.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/_cell.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/_details.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/_index.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/_open.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/cell.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/details.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/open.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/truncate_by_height.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/create_doc_table_react.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.html delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.test.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/doc_table_strings.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/index.scss delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/infinite_scroll.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_default_sort.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort_for_search_source.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/index.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/pager.js delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/pager_factory.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_viewer.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/doc_viewer_links.tsx delete mode 100644 src/plugins/discover_legacy/public/application/angular/helpers/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/helpers/point_series.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/redirect.ts delete mode 100644 src/plugins/discover_legacy/public/application/angular/response_handler.js delete mode 100644 src/plugins/discover_legacy/public/application/application.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message_directive.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/context_error_message/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/create_discover_legacy_directive.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/discover_legacy.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc/doc.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc/doc.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc/use_opensearch_doc_search.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc/use_opensearch_doc_search.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/__snapshots__/doc_viewer_render_tab.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.scss delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_error.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_tab.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_tab.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_tab.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer_links/__snapshots__/doc_viewer_links.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer_links/doc_viewer_links.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/doc_viewer_links/doc_viewer_links.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/field_name/__snapshots__/field_name.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/components/field_name/field_name.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/field_name/field_name.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/field_name/field_type_name.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/help_menu/help_menu_util.js delete mode 100644 src/plugins/discover_legacy/public/application/components/hits_counter/hits_counter.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/hits_counter/hits_counter.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/hits_counter/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/json_code_block/__snapshots__/json_code_block.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/components/json_code_block/json_code_block.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/json_code_block/json_code_block.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/loading_spinner/loading_spinner.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/loading_spinner/loading_spinner.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/__snapshots__/discover_index_pattern.test.tsx.snap delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/change_indexpattern.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field.scss delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field_bucket.scss delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field_bucket.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.scss delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field_search.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_field_search.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern_title.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.scss delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/field_calculator.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/field_calculator.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/field_filter.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/field_filter.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/get_details.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/get_field_type_name.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/get_index_pattern_field_list.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/get_warnings.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/group_fields.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/group_fields.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/lib/visualize_trigger_utils.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/string_progress_bar.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/sidebar/types.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/skip_bottom_button/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/skip_bottom_button/skip_bottom_button.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/skip_bottom_button/skip_bottom_button.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_helper.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_helper.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_row.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_row_btn_collapse.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_add.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_exists.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_remove.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_row_btn_toggle_column.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_row_icon_no_mapping.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/table/table_row_icon_underscore.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/timechart_header/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/components/timechart_header/timechart_header.test.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/timechart_header/timechart_header.tsx delete mode 100644 src/plugins/discover_legacy/public/application/components/top_nav/__snapshots__/open_search_panel.test.js.snap delete mode 100644 src/plugins/discover_legacy/public/application/components/top_nav/open_search_panel.js delete mode 100644 src/plugins/discover_legacy/public/application/components/top_nav/open_search_panel.test.js delete mode 100644 src/plugins/discover_legacy/public/application/components/top_nav/show_open_search_panel.js delete mode 100644 src/plugins/discover_legacy/public/application/doc_views/doc_views_helpers.tsx delete mode 100644 src/plugins/discover_legacy/public/application/doc_views/doc_views_registry.ts delete mode 100644 src/plugins/discover_legacy/public/application/doc_views/doc_views_types.ts delete mode 100644 src/plugins/discover_legacy/public/application/doc_views_links/doc_views_links_registry.ts delete mode 100644 src/plugins/discover_legacy/public/application/doc_views_links/doc_views_links_types.ts delete mode 100644 src/plugins/discover_legacy/public/application/embeddable/constants.ts delete mode 100644 src/plugins/discover_legacy/public/application/embeddable/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/embeddable/search_embeddable.scss delete mode 100644 src/plugins/discover_legacy/public/application/embeddable/search_embeddable.ts delete mode 100644 src/plugins/discover_legacy/public/application/embeddable/search_embeddable_factory.ts delete mode 100644 src/plugins/discover_legacy/public/application/embeddable/search_template.html delete mode 100644 src/plugins/discover_legacy/public/application/embeddable/types.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/breadcrumbs.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/format_number_with_commas.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/get_index_pattern_id.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/get_switch_index_pattern_app_state.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/get_switch_index_pattern_app_state.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/index.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/migrate_legacy_query.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/popularize_field.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/popularize_field.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/shorten_dotted_string.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/validate_time_range.test.ts delete mode 100644 src/plugins/discover_legacy/public/application/helpers/validate_time_range.ts delete mode 100644 src/plugins/discover_legacy/public/application/index.scss delete mode 100644 src/plugins/discover_legacy/public/build_services.ts delete mode 100644 src/plugins/discover_legacy/public/get_inner_angular.ts delete mode 100644 src/plugins/discover_legacy/public/index.ts delete mode 100644 src/plugins/discover_legacy/public/mocks.ts delete mode 100644 src/plugins/discover_legacy/public/opensearch_dashboards_services.ts delete mode 100644 src/plugins/discover_legacy/public/plugin.ts delete mode 100644 src/plugins/discover_legacy/public/saved_searches/_saved_search.ts delete mode 100644 src/plugins/discover_legacy/public/saved_searches/index.ts delete mode 100644 src/plugins/discover_legacy/public/saved_searches/saved_searches.ts delete mode 100644 src/plugins/discover_legacy/public/saved_searches/types.ts delete mode 100644 src/plugins/discover_legacy/public/url_generator.test.ts delete mode 100644 src/plugins/discover_legacy/public/url_generator.ts delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular/angular_config.tsx delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular/index.ts delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular/osd_top_nav.js delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular/promises.js delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular/subscribe_with_scope.test.ts delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular/subscribe_with_scope.ts delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular/watch_multi.js delete mode 100755 src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/bind_html/bind_html.js delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/index.ts delete mode 100755 src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/position.js delete mode 100755 src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip.js delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip_html_unsafe_popup.html delete mode 100644 src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip_popup.html diff --git a/package.json b/package.json index 0cffb3fcc47e..eb2206dfcf21 100644 --- a/package.json +++ b/package.json @@ -158,9 +158,6 @@ "JSONStream": "1.3.5", "abortcontroller-polyfill": "^1.4.0", "ajv": "^8.11.0", - "angular": "^1.8.2", - "angular-elastic": "^2.5.1", - "angular-sanitize": "^1.8.0", "bluebird": "3.5.5", "chalk": "^4.1.0", "chokidar": "^3.4.2", @@ -262,8 +259,6 @@ "@testing-library/jest-dom": "^5.16.2", "@testing-library/react": "^12.1.2", "@testing-library/react-hooks": "^7.0.2", - "@types/angular": "^1.8.4", - "@types/angular-mocks": "^1.7.1", "@types/archiver": "^5.3.1", "@types/babel__core": "^7.1.17", "@types/bluebird": "^3.1.1", @@ -344,10 +339,6 @@ "@types/zen-observable": "^0.8.0", "@typescript-eslint/eslint-plugin": "^3.10.0", "@typescript-eslint/parser": "^3.10.0", - "angular-aria": "^1.8.0", - "angular-mocks": "^1.8.2", - "angular-recursion": "^1.0.5", - "angular-route": "^1.8.0", "archiver": "^5.3.0", "axe-core": "^4.0.2", "babel-eslint": "^10.0.3", @@ -424,7 +415,6 @@ "ms-chromium-edge-driver": "^0.4.3", "murmurhash3js": "3.0.1", "mutation-observer": "^1.0.3", - "ngreact": "^0.5.1", "nock": "12.0.3", "node-stream-zip": "^1.15.0", "normalize-path": "^3.0.0", @@ -476,4 +466,4 @@ "node": ">=14.20.1 <19", "yarn": "^1.22.10" } -} +} \ No newline at end of file diff --git a/packages/osd-i18n/src/angular/__snapshots__/directive.test.ts.snap b/packages/osd-i18n/src/angular/__snapshots__/directive.test.ts.snap deleted file mode 100644 index 44bb96399432..000000000000 --- a/packages/osd-i18n/src/angular/__snapshots__/directive.test.ts.snap +++ /dev/null @@ -1,69 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`i18nDirective doesn't render html in result message with text-only values 1`] = ` -
- Default <span onclick=alert(1) >Press</span> message -
-`; - -exports[`i18nDirective doesn't render html in text-only value 1`] = ` -
- Default <strong>message</strong> -
-`; - -exports[`i18nDirective inserts correct translation html content with values 1`] = `"default-message word"`; - -exports[`i18nDirective inserts correct translation html content with values 2`] = `"default-message anotherWord"`; - -exports[`i18nDirective sanitizes message before inserting it to DOM 1`] = ` -
' }" -> - Default message, -
-
-`; - -exports[`i18nDirective sanitizes onclick attribute 1`] = ` -
- Default - - Press - - message -
-`; - -exports[`i18nDirective sanitizes onmouseover attribute 1`] = ` -
Press' }" -> - Default - - Press - - message -
-`; diff --git a/packages/osd-i18n/src/angular/directive.test.ts b/packages/osd-i18n/src/angular/directive.test.ts deleted file mode 100644 index 35dd43001335..000000000000 --- a/packages/osd-i18n/src/angular/directive.test.ts +++ /dev/null @@ -1,172 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 angular from 'angular'; -import 'angular-mocks'; -import 'angular-sanitize'; - -import { i18nDirective } from './directive'; -import { I18nProvider } from './provider'; - -angular - .module('app', ['ngSanitize']) - .provider('i18n', I18nProvider) - .directive('i18nId', i18nDirective); - -describe('i18nDirective', () => { - let compile: angular.ICompileService; - let scope: angular.IRootScopeService & { word?: string }; - - beforeEach(angular.mock.module('app')); - beforeEach( - angular.mock.inject( - ($compile: angular.ICompileService, $rootScope: angular.IRootScopeService) => { - compile = $compile; - scope = $rootScope.$new(); - scope.word = 'word'; - } - ) - ); - - test('inserts correct translation html content', () => { - const id = 'id'; - const defaultMessage = 'default-message'; - - const element = angular.element( - `
` - ); - - compile(element)(scope); - scope.$digest(); - - expect(element.html()).toEqual(defaultMessage); - }); - - test('inserts correct translation html content with values', () => { - const id = 'id'; - const defaultMessage = 'default-message {word}'; - - const element = angular.element( - `
` - ); - - compile(element)(scope); - scope.$digest(); - - expect(element.html()).toMatchSnapshot(); - - scope.word = 'anotherWord'; - scope.$digest(); - - expect(element.html()).toMatchSnapshot(); - }); - - test('sanitizes message before inserting it to DOM', () => { - const element = angular.element( - `
` - ); - - compile(element)(scope); - scope.$digest(); - - expect(element[0]).toMatchSnapshot(); - }); - - test(`doesn't render html in result message with text-only values`, () => { - const element = angular.element( - `
` - ); - - compile(element)(scope); - scope.$digest(); - - expect(element[0]).toMatchSnapshot(); - }); - - test('sanitizes onclick attribute', () => { - const element = angular.element( - `
` - ); - - compile(element)(scope); - scope.$digest(); - - expect(element[0]).toMatchSnapshot(); - }); - - test('sanitizes onmouseover attribute', () => { - const element = angular.element( - `
` - ); - - compile(element)(scope); - scope.$digest(); - - expect(element[0]).toMatchSnapshot(); - }); - - test(`doesn't render html in text-only value`, () => { - const element = angular.element( - `
` - ); - - compile(element)(scope); - scope.$digest(); - - expect(element[0]).toMatchSnapshot(); - }); -}); diff --git a/packages/osd-i18n/src/angular/directive.ts b/packages/osd-i18n/src/angular/directive.ts deleted file mode 100644 index 790357da7d46..000000000000 --- a/packages/osd-i18n/src/angular/directive.ts +++ /dev/null @@ -1,126 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { IDirective, IRootElementService, IScope } from 'angular'; - -import { I18nServiceType } from './provider'; - -interface I18nScope extends IScope { - values?: Record; - defaultMessage: string; - id: string; -} - -const HTML_KEY_PREFIX = 'html_'; -const PLACEHOLDER_SEPARATOR = '@I18N@'; - -export const i18nDirective: [string, string, typeof i18nDirectiveFn] = [ - 'i18n', - '$sanitize', - i18nDirectiveFn, -]; - -function i18nDirectiveFn( - i18n: I18nServiceType, - $sanitize: (html: string) => string -): IDirective { - return { - restrict: 'A', - scope: { - id: '@i18nId', - defaultMessage: '@i18nDefaultMessage', - values: ' { - setContent($element, $scope, $sanitize, i18n); - }); - } else { - setContent($element, $scope, $sanitize, i18n); - } - }, - }; -} - -function setContent( - $element: IRootElementService, - $scope: I18nScope, - $sanitize: (html: string) => string, - i18n: I18nServiceType -) { - const originalValues = $scope.values; - const valuesWithPlaceholders = {} as Record; - let hasValuesWithPlaceholders = false; - - // If we have values with the keys that start with HTML_KEY_PREFIX we should replace - // them with special placeholders that later on will be inserted as HTML - // into the DOM, the rest of the content will be treated as text. We don't - // sanitize values at this stage as some of the values can be excluded from - // the translated string (e.g. not used by ICU conditional statements). - if (originalValues) { - for (const [key, value] of Object.entries(originalValues)) { - if (key.startsWith(HTML_KEY_PREFIX)) { - valuesWithPlaceholders[ - key.slice(HTML_KEY_PREFIX.length) - ] = `${PLACEHOLDER_SEPARATOR}${key}${PLACEHOLDER_SEPARATOR}`; - - hasValuesWithPlaceholders = true; - } else { - valuesWithPlaceholders[key] = value; - } - } - } - - const label = i18n($scope.id, { - values: valuesWithPlaceholders, - defaultMessage: $scope.defaultMessage, - }); - - // If there are no placeholders to replace treat everything as text, otherwise - // insert label piece by piece replacing every placeholder with corresponding - // sanitized HTML content. - if (!hasValuesWithPlaceholders) { - $element.text(label); - } else { - $element.empty(); - for (const contentOrPlaceholder of label.split(PLACEHOLDER_SEPARATOR)) { - if (!contentOrPlaceholder) { - continue; - } - - $element.append( - originalValues!.hasOwnProperty(contentOrPlaceholder) - ? $sanitize(originalValues![contentOrPlaceholder]) - : document.createTextNode(contentOrPlaceholder) - ); - } - } -} diff --git a/packages/osd-i18n/src/angular/filter.test.ts b/packages/osd-i18n/src/angular/filter.test.ts deleted file mode 100644 index bc236e711d4c..000000000000 --- a/packages/osd-i18n/src/angular/filter.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -jest.mock('../core/i18n', () => ({ - translate: jest.fn().mockImplementation(() => 'translation'), -})); - -import angular from 'angular'; -import 'angular-mocks'; - -import * as i18n from '../core/i18n'; -import { i18nFilter as angularI18nFilter } from './filter'; -import { I18nProvider, I18nServiceType } from './provider'; - -angular.module('app', []).provider('i18n', I18nProvider).filter('i18n', angularI18nFilter); - -describe('i18nFilter', () => { - let filter: I18nServiceType; - - beforeEach(angular.mock.module('app')); - beforeEach( - angular.mock.inject((i18nFilter) => { - filter = i18nFilter; - }) - ); - afterEach(() => { - jest.resetAllMocks(); - }); - - test('provides wrapper around i18n engine', () => { - const id = 'id'; - const defaultMessage = 'default-message'; - const values = {}; - - const result = filter(id, { defaultMessage, values }); - - expect(result).toEqual('translation'); - expect(i18n.translate).toHaveBeenCalledTimes(1); - expect(i18n.translate).toHaveBeenCalledWith(id, { defaultMessage, values }); - }); -}); diff --git a/packages/osd-i18n/src/angular/filter.ts b/packages/osd-i18n/src/angular/filter.ts deleted file mode 100644 index 4ffa5dd3ef4e..000000000000 --- a/packages/osd-i18n/src/angular/filter.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { I18nServiceType } from './provider'; - -export const i18nFilter: [string, typeof i18nFilterFn] = ['i18n', i18nFilterFn]; - -function i18nFilterFn(i18n: I18nServiceType) { - return (id: string, { defaultMessage = '', values = {} } = {}) => { - return i18n(id, { - values, - defaultMessage, - }); - }; -} diff --git a/packages/osd-i18n/src/angular/index.ts b/packages/osd-i18n/src/angular/index.ts deleted file mode 100644 index 04f7d66eb12a..000000000000 --- a/packages/osd-i18n/src/angular/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { I18nProvider } from './provider'; - -export { i18nFilter } from './filter'; -export { i18nDirective } from './directive'; - -// re-export types: https://github.com/babel/babel-loader/issues/603 -import { I18nServiceType as _I18nServiceType } from './provider'; -export type I18nServiceType = _I18nServiceType; diff --git a/packages/osd-i18n/src/angular/provider.test.ts b/packages/osd-i18n/src/angular/provider.test.ts deleted file mode 100644 index e612e0bef3d8..000000000000 --- a/packages/osd-i18n/src/angular/provider.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 angular from 'angular'; -import 'angular-mocks'; - -import * as i18nCore from '../core/i18n'; -import { I18nProvider, I18nServiceType } from './provider'; - -angular.module('app', []).provider('i18n', I18nProvider); - -describe('i18nProvider', () => { - let provider: I18nProvider; - let service: I18nServiceType; - - beforeEach( - angular.mock.module('app', [ - 'i18nProvider', - (i18n: I18nProvider) => { - provider = i18n; - }, - ]) - ); - beforeEach( - angular.mock.inject((i18n: I18nServiceType) => { - service = i18n; - }) - ); - - test('provides wrapper around i18n engine', () => { - expect(service).toEqual(i18nCore.translate); - }); - - test('provides service wrapper around i18n engine', () => { - const serviceMethodNames = Object.keys(provider); - const pluginMethodNames = Object.keys(i18nCore); - - expect([...serviceMethodNames, 'translate'].sort()).toEqual( - [...pluginMethodNames, '$get'].sort() - ); - }); -}); diff --git a/packages/osd-i18n/src/angular/provider.ts b/packages/osd-i18n/src/angular/provider.ts deleted file mode 100644 index bd02a30cef45..000000000000 --- a/packages/osd-i18n/src/angular/provider.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 * as i18n from '../core'; - -export type I18nServiceType = ReturnType; - -export class I18nProvider implements angular.IServiceProvider { - public addTranslation = i18n.addTranslation; - public getTranslation = i18n.getTranslation; - public setLocale = i18n.setLocale; - public getLocale = i18n.getLocale; - public setDefaultLocale = i18n.setDefaultLocale; - public getDefaultLocale = i18n.getDefaultLocale; - public setFormats = i18n.setFormats; - public getFormats = i18n.getFormats; - public getRegisteredLocales = i18n.getRegisteredLocales; - public init = i18n.init; - public load = i18n.load; - public $get = () => i18n.translate; -} diff --git a/packages/osd-stylelint-config/config/global_selectors.json b/packages/osd-stylelint-config/config/global_selectors.json index 760717c8dab5..d89561a04cbc 100644 --- a/packages/osd-stylelint-config/config/global_selectors.json +++ b/packages/osd-stylelint-config/config/global_selectors.json @@ -23,9 +23,7 @@ "src/plugins/vis_builder/public/application/components/searchable_dropdown.scss", "src/plugins/vis_builder/public/application/components/side_nav.scss", "packages/osd-ui-framework/src/components/button/button_group/_button_group.scss", - "src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.scss", - "src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/_open.scss", "src/plugins/discover/public/application/components/data_grid/data_grid_table_cell_value.scss" ] } -} +} \ No newline at end of file diff --git a/packages/osd-ui-framework/src/components/local_nav/_local_date_picker.scss b/packages/osd-ui-framework/src/components/local_nav/_local_date_picker.scss index 0a38a115c4a0..ec60ffb4a918 100644 --- a/packages/osd-ui-framework/src/components/local_nav/_local_date_picker.scss +++ b/packages/osd-ui-framework/src/components/local_nav/_local_date_picker.scss @@ -54,19 +54,6 @@ .kuiDatePickerRowCell { padding: 0; text-align: center; - - /** - * This state class exists to support weird angular-bootstrap datepicker functionality, - * in which you can't select a day on the "From" calendar if it falls after the selected day in - * the "To" calendar (and vice versa, you can't select a "To" day if it is before the "From" day). - */ - &.kuiDatePickerRowCell-isBlocked { - cursor: not-allowed; - - .kuiDatePickerRowCellContent { - pointer-events: none; - } - } } /** diff --git a/packages/osd-ui-shared-deps/entry.js b/packages/osd-ui-shared-deps/entry.js index 813fe512a554..8afb2b08da6c 100644 --- a/packages/osd-ui-shared-deps/entry.js +++ b/packages/osd-ui-shared-deps/entry.js @@ -30,16 +30,13 @@ require('./polyfills'); -// must load before angular export const Jquery = require('jquery'); window.$ = window.jQuery = Jquery; require('./flot_charts'); // stateful deps export const OsdI18n = require('@osd/i18n'); -export const OsdI18nAngular = require('@osd/i18n/angular'); export const OsdI18nReact = require('@osd/i18n/react'); -export const Angular = require('angular'); export const Moment = require('moment'); export const MomentTimezone = require('moment-timezone/moment-timezone'); export const OsdMonaco = require('@osd/monaco'); diff --git a/packages/osd-ui-shared-deps/index.js b/packages/osd-ui-shared-deps/index.js index 1ebd54a55a97..36218a28d4eb 100644 --- a/packages/osd-ui-shared-deps/index.js +++ b/packages/osd-ui-shared-deps/index.js @@ -40,9 +40,7 @@ exports.darkCssDistFilename = 'osd-ui-shared-deps.v7.dark.css'; exports.darkV8CssDistFilename = 'osd-ui-shared-deps.v8.dark.css'; exports.externals = { // stateful deps - angular: '__osdSharedDeps__.Angular', '@osd/i18n': '__osdSharedDeps__.OsdI18n', - '@osd/i18n/angular': '__osdSharedDeps__.OsdI18nAngular', '@osd/i18n/react': '__osdSharedDeps__.OsdI18nReact', jquery: '__osdSharedDeps__.Jquery', moment: '__osdSharedDeps__.Moment', diff --git a/packages/osd-ui-shared-deps/package.json b/packages/osd-ui-shared-deps/package.json index fca9abd7c537..ca6028d56acc 100644 --- a/packages/osd-ui-shared-deps/package.json +++ b/packages/osd-ui-shared-deps/package.json @@ -16,7 +16,6 @@ "@osd/i18n": "1.0.0", "@osd/monaco": "1.0.0", "abortcontroller-polyfill": "^1.4.0", - "angular": "^1.8.2", "axios": "^0.27.2", "compression-webpack-plugin": "npm:@amoo-miki/compression-webpack-plugin@4.0.1-rc.1", "core-js": "^3.6.5", @@ -52,4 +51,4 @@ "val-loader": "^2.1.2", "webpack": "npm:@amoo-miki/webpack@4.46.0-rc.2" } -} +} \ No newline at end of file diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 956bb5a7a836..dd874d3419f2 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -80,7 +80,6 @@ import { withNotifyOnErrors, } from '../../opensearch_dashboards_utils/public'; import { - initAngularBootstrap, OpenSearchDashboardsLegacySetup, OpenSearchDashboardsLegacyStart, } from '../../opensearch_dashboards_legacy/public'; @@ -452,9 +451,6 @@ export class DashboardPlugin }, }; - // TODO: delete this when discover de-angular is completed - initAngularBootstrap(); - core.application.register(app); urlForwarding.forwardApp( DashboardConstants.DASHBOARDS_ID, diff --git a/src/plugins/discover/common/index.ts b/src/plugins/discover/common/index.ts index 0cac73333e25..45887df880ae 100644 --- a/src/plugins/discover/common/index.ts +++ b/src/plugins/discover/common/index.ts @@ -4,7 +4,6 @@ */ export const PLUGIN_ID = 'discover'; -export const NEW_DISCOVER_APP = 'discover:v2'; export const DEFAULT_COLUMNS_SETTING = 'defaultColumns'; export const SAMPLE_SIZE_SETTING = 'discover:sampleSize'; export const AGGS_TERMS_SIZE_SETTING = 'discover:aggs:terms:size'; diff --git a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx index 8c19d38eb20d..3a0cdd17d238 100644 --- a/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx +++ b/src/plugins/discover/public/application/components/top_nav/get_top_nav_links.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { DiscoverViewServices } from '../../../build_services'; import { showOpenSearchPanel } from './show_open_search_panel'; import { SavedSearch } from '../../../saved_searches'; -import { NEW_DISCOVER_APP } from '../../../../common'; import { Adapters } from '../../../../../inspector/public'; import { TopNavMenuData } from '../../../../../navigation/public'; import { ISearchSource, unhashUrl } from '../../../opensearch_dashboards_services'; @@ -30,7 +29,6 @@ export const getTopNavLinks = ( history, inspector, core, - uiSettings, capabilities, share, toastNotifications, @@ -194,7 +192,7 @@ export const getTopNavLinks = ( share?.toggleShareContextMenu({ anchorElement, allowEmbed: false, - allowShortUrl: capabilities.discover.createShortUrl as boolean, + allowShortUrl: capabilities.discover?.createShortUrl as boolean, shareableUrl: unhashUrl(window.location.href), objectId: savedSearch.id, objectType: 'search', @@ -223,27 +221,9 @@ export const getTopNavLinks = ( }, }; - const legacyDiscover: TopNavMenuData = { - id: 'discover-new', - label: i18n.translate('discover.localMenu.newDiscoverTitle', { - defaultMessage: 'New Discover', - }), - description: i18n.translate('discover.localMenu.newDiscoverDescription', { - defaultMessage: 'New Discover Experience', - }), - testId: 'discoverNewButton', - run: async () => { - await uiSettings.set(NEW_DISCOVER_APP, false); - window.location.reload(); - }, - type: 'toggle' as const, - emphasize: true, - }; - return [ - legacyDiscover, newSearch, - ...(capabilities.discover.save ? [saveSearch] : []), + ...(capabilities.discover?.save ? [saveSearch] : []), openSearch, ...(share ? [shareSearch] : []), // Show share option only if share plugin is available inspectSearch, diff --git a/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx b/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx index 7a777142d2f0..4a8ebfb1bf29 100644 --- a/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx +++ b/src/plugins/discover/public/application/view_components/canvas/top_nav.tsx @@ -5,7 +5,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { AppMountParameters } from '../../../../../../core/public'; -import { NEW_DISCOVER_APP, PLUGIN_ID } from '../../../../common'; +import { PLUGIN_ID } from '../../../../common'; import { useOpenSearchDashboards } from '../../../../../opensearch_dashboards_react/public'; import { DiscoverViewServices } from '../../../build_services'; import { IndexPattern } from '../../../opensearch_dashboards_services'; @@ -25,12 +25,11 @@ export const TopNav = ({ opts }: TopNavProps) => { const [indexPatterns, setIndexPatterns] = useState(undefined); const { - uiSettings, navigation: { ui: { TopNavMenu }, }, core: { - application: { navigateToApp, getUrlForApp }, + application: { getUrlForApp }, }, data, chrome, @@ -38,18 +37,6 @@ export const TopNav = ({ opts }: TopNavProps) => { const topNavLinks = savedSearch ? getTopNavLinks(services, inspectorAdapters, savedSearch) : []; - useEffect(() => { - if (uiSettings.get(NEW_DISCOVER_APP) === false) { - const path = window.location.hash; - navigateToApp('discoverLegacy', { - replace: true, - path, - }); - } - - return () => {}; - }, [navigateToApp, uiSettings]); - useEffect(() => { let isMounted = true; const getDefaultIndexPattern = async () => { diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts index 3bc009914940..191ecf14cbbf 100644 --- a/src/plugins/discover/public/index.ts +++ b/src/plugins/discover/public/index.ts @@ -40,4 +40,3 @@ export { SavedSearch, SavedSearchLoader, createSavedSearchesLoader } from './sav // TODO: Fix embeddable after removing Angular // export { ISearchEmbeddable, SEARCH_EMBEDDABLE_TYPE, SearchInput } from './application/embeddable'; export { DISCOVER_APP_URL_GENERATOR, DiscoverUrlGeneratorState } from './url_generator'; -export { NEW_DISCOVER_APP } from '../common'; diff --git a/src/plugins/discover/public/plugin.ts b/src/plugins/discover/public/plugin.ts index f1532b6f776b..e14272e090ba 100644 --- a/src/plugins/discover/public/plugin.ts +++ b/src/plugins/discover/public/plugin.ts @@ -60,7 +60,7 @@ import { DiscoverUrlGenerator, } from './url_generator'; // import { SearchEmbeddableFactory } from './application/embeddable'; -import { NEW_DISCOVER_APP, PLUGIN_ID } from '../common'; +import { PLUGIN_ID } from '../common'; import { DataExplorerPluginSetup } from '../../data_explorer/public'; import { registerFeature } from './register_feature'; import { @@ -266,55 +266,45 @@ export class DiscoverPlugin // This is for instances where the user navigates to the app from the application nav menu const path = window.location.hash; - const v2Enabled = await core.uiSettings.get(NEW_DISCOVER_APP); - - if (!v2Enabled) { - navigateToApp('discoverLegacy', { + const newPath = migrateUrlState(path); + if (newPath.startsWith('#/context') || newPath.startsWith('#/doc')) { + const { renderDocView } = await import('./application/components/doc_views'); + const unmount = renderDocView(params.element); + return () => { + unmount(); + }; + } else { + navigateToApp('data-explorer', { replace: true, - path, + path: `/${PLUGIN_ID}${newPath}`, }); - } else { - const newPath = migrateUrlState(path); - if (newPath.startsWith('#/context') || newPath.startsWith('#/doc')) { - const { renderDocView } = await import('./application/components/doc_views'); - const unmount = renderDocView(params.element); - return () => { - unmount(); - }; - } else { - navigateToApp('data-explorer', { - replace: true, - path: `/${PLUGIN_ID}${newPath}`, - }); - } } return () => {}; }, }); - // TODO: These routes need to be handled for Discover 2.0 to support legacy saved URLS's - // plugins.urlForwarding.forwardApp('doc', 'discover', (path) => { - // return `#${path}`; - // }); - // plugins.urlForwarding.forwardApp('context', 'discover', (path) => { - // const urlParts = path.split('/'); - // // take care of urls containing legacy url, those split in the following way - // // ["", "context", indexPatternId, _type, id + params] - // if (urlParts[4]) { - // // remove _type part - // const newPath = [...urlParts.slice(0, 3), ...urlParts.slice(4)].join('/'); - // return `#${newPath}`; - // } - // return `#${path}`; - // }); - // plugins.urlForwarding.forwardApp('discover', 'discover', (path) => { - // const [, id, tail] = /discover\/([^\?]+)(.*)/.exec(path) || []; - // if (!id) { - // return `#${path.replace('/discover', '') || '/'}`; - // } - // return `#/view/${id}${tail || ''}`; - // }); + plugins.urlForwarding.forwardApp('doc', 'discover', (path) => { + return `#${path}`; + }); + plugins.urlForwarding.forwardApp('context', 'discover', (path) => { + const urlParts = path.split('/'); + // take care of urls containing legacy url, those split in the following way + // ["", "context", indexPatternId, _type, id + params] + if (urlParts[4]) { + // remove _type part + const newPath = [...urlParts.slice(0, 3), ...urlParts.slice(4)].join('/'); + return `#${newPath}`; + } + return `#${path}`; + }); + plugins.urlForwarding.forwardApp('discover', 'discover', (path) => { + const [, id, tail] = /discover\/([^\?]+)(.*)/.exec(path) || []; + if (!id) { + return `#${path.replace('/discover', '') || '/'}`; + } + return `#/view/${id}${tail || ''}`; + }); if (plugins.home) { registerFeature(plugins.home); diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index 2b35384c2e5c..70eab306e7fb 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -33,7 +33,6 @@ import { schema } from '@osd/config-schema'; import { UiSettingsParams } from 'opensearch-dashboards/server'; import { - NEW_DISCOVER_APP, DEFAULT_COLUMNS_SETTING, SAMPLE_SIZE_SETTING, AGGS_TERMS_SIZE_SETTING, @@ -48,17 +47,6 @@ import { } from '../common'; export const uiSettings: Record = { - [NEW_DISCOVER_APP]: { - name: i18n.translate('discover.advancedSettings.legacyToggleTitle', { - defaultMessage: 'Enable new discover app', - }), - value: true, - description: i18n.translate('discover.advancedSettings.legacyToggleText', { - defaultMessage: 'Disabling the new discover app will redirect to the legacy app.', - }), - category: ['discover'], - schema: schema.boolean(), - }, [DEFAULT_COLUMNS_SETTING]: { name: i18n.translate('discover.advancedSettings.defaultColumnsTitle', { defaultMessage: 'Default columns', diff --git a/src/plugins/discover_legacy/README.md b/src/plugins/discover_legacy/README.md deleted file mode 100644 index a914d651eef3..000000000000 --- a/src/plugins/discover_legacy/README.md +++ /dev/null @@ -1 +0,0 @@ -Contains the Discover application and the saved search embeddable. \ No newline at end of file diff --git a/src/plugins/discover_legacy/common/index.ts b/src/plugins/discover_legacy/common/index.ts deleted file mode 100644 index 371442385bbf..000000000000 --- a/src/plugins/discover_legacy/common/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 DEFAULT_COLUMNS_SETTING = 'defaultColumns'; -export const SAMPLE_SIZE_SETTING = 'discover:sampleSize'; -export const AGGS_TERMS_SIZE_SETTING = 'discover:aggs:terms:size'; -export const SORT_DEFAULT_ORDER_SETTING = 'discover:sort:defaultOrder'; -export const SEARCH_ON_PAGE_LOAD_SETTING = 'discover:searchOnPageLoad'; -export const DOC_HIDE_TIME_COLUMN_SETTING = 'doc_table:hideTimeColumn'; -export const FIELDS_LIMIT_SETTING = 'fields:popularLimit'; -export const CONTEXT_DEFAULT_SIZE_SETTING = 'context:defaultSize'; -export const CONTEXT_STEP_SETTING = 'context:step'; -export const CONTEXT_TIE_BREAKER_FIELDS_SETTING = 'context:tieBreakerFields'; -export const MODIFY_COLUMNS_ON_SWITCH = 'discover:modifyColumnsOnSwitch'; diff --git a/src/plugins/discover_legacy/opensearch_dashboards.json b/src/plugins/discover_legacy/opensearch_dashboards.json deleted file mode 100644 index 6a4259a41d75..000000000000 --- a/src/plugins/discover_legacy/opensearch_dashboards.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "discoverLegacy", - "version": "opensearchDashboards", - "server": false, - "ui": true, - "requiredPlugins": [ - "charts", - "data", - "embeddable", - "inspector", - "opensearchDashboardsLegacy", - "urlForwarding", - "navigation", - "uiActions", - "visualizations" - ], - "optionalPlugins": [ - "home", - "share" - ], - "requiredBundles": [ - "opensearchDashboardsUtils", - "savedObjects", - "opensearchDashboardsReact", - "discover" - ] -} \ No newline at end of file diff --git a/src/plugins/discover_legacy/public/application/_discover.scss b/src/plugins/discover_legacy/public/application/_discover.scss deleted file mode 100644 index f574357c5ff4..000000000000 --- a/src/plugins/discover_legacy/public/application/_discover.scss +++ /dev/null @@ -1,164 +0,0 @@ -.dscAppWrapper { - display: flex; - flex-direction: column; - flex-grow: 1; - overflow: hidden; -} - -.dscAppContainer { - > * { - position: relative; - } -} - -discover-app { - flex-grow: 1; -} - -.dscHistogram { - display: flex; - height: 200px; - padding: $euiSizeS; -} - -// SASSTODO: replace the z-index value with a variable -.dscWrapper { - padding-left: $euiSizeXL; - padding-right: $euiSizeS; - z-index: 1; - - @include euiBreakpoint("xs", "s", "m") { - padding-left: $euiSizeS; - } -} - -@include euiPanel(".dscWrapper__content"); - -.dscWrapper__content { - padding-top: $euiSizeXS; - background-color: $euiColorEmptyShade; - - .osd-table { - margin-bottom: 0; - } -} - -.dscTimechart { - display: block; - position: relative; - - // SASSTODO: the visualizing component should have an option or a modifier - .series > rect { - fill-opacity: 0.5; - stroke-width: 1; - } -} - -.dscResultCount { - padding-top: $euiSizeXS; -} - -.dscTimechart__header { - display: flex; - justify-content: center; - min-height: $euiSizeXXL; - padding: $euiSizeXS 0; -} - -.dscOverlay { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 20; - padding-top: $euiSizeM; - opacity: 0.75; - text-align: center; - background-color: transparent; -} - -.dscTable { - overflow: auto; - - // SASSTODO: add a monospace modifier to the doc-table component - .osdDocTable__row { - font-family: $euiCodeFontFamily; - font-size: $euiFontSizeXS; - } -} - -// SASSTODO: replace the padding value with a variable -.dscTable__footer { - background-color: $euiColorLightShade; - padding: 5px 10px; - text-align: center; -} - -.dscResults { - h3 { - margin: -20px 0 10px; - text-align: center; - } -} - -.dscResults__interval { - display: inline-block; - width: auto; -} - -.dscSkipButton { - position: absolute; - right: $euiSizeM; - top: $euiSizeXS; -} - -.dscTableFixedScroll { - overflow-x: auto; - padding-bottom: 0; - - + .dscTableFixedScroll__scroller { - position: fixed; - bottom: 0; - overflow-x: auto; - overflow-y: hidden; - } -} - -.dscCollapsibleSidebar { - position: relative; - z-index: $euiZLevel1; - - .dscCollapsibleSidebar__collapseButton { - position: absolute; - top: 0; - right: -$euiSizeXL + 4; - cursor: pointer; - z-index: -1; - min-height: $euiSizeM; - min-width: $euiSizeM; - padding: $euiSizeXS * 0.5; - } - - &.closed { - width: 0 !important; - border-right-width: 0; - border-left-width: 0; - - .dscCollapsibleSidebar__collapseButton { - right: -$euiSizeL + 4; - } - } -} - -@include euiBreakpoint("xs", "s", "m") { - .dscCollapsibleSidebar { - &.closed { - display: none; - } - - .dscCollapsibleSidebar__collapseButton { - display: none; - } - } -} diff --git a/src/plugins/discover_legacy/public/application/angular/_index.scss b/src/plugins/discover_legacy/public/application/angular/_index.scss deleted file mode 100644 index acc755e4a170..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import "directives/index"; -@import "context/index"; diff --git a/src/plugins/discover_legacy/public/application/angular/context.html b/src/plugins/discover_legacy/public/application/angular/context.html deleted file mode 100644 index 2c8e9a2a5d6f..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context.html +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/src/plugins/discover_legacy/public/application/angular/context.js b/src/plugins/discover_legacy/public/application/angular/context.js deleted file mode 100644 index 4757102315c0..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { i18n } from '@osd/i18n'; -import { CONTEXT_DEFAULT_SIZE_SETTING } from '../../../common'; -import { getAngularModule, getServices } from '../../opensearch_dashboards_services'; -import './context_app'; -import { getState } from './context_state'; -import contextAppRouteTemplate from './context.html'; -import { getRootBreadcrumbs } from '../helpers/breadcrumbs'; - -const k7Breadcrumbs = ($route) => { - const { indexPattern } = $route.current.locals; - const { id } = $route.current.params; - - return [ - ...getRootBreadcrumbs(), - { - text: i18n.translate('discover.context.breadcrumb', { - defaultMessage: 'Context of {indexPatternTitle}#{docId}', - values: { - indexPatternTitle: indexPattern.title, - docId: id, - }, - }), - }, - ]; -}; - -getAngularModule().config(($routeProvider) => { - $routeProvider.when('/context/:indexPatternId/:id*', { - controller: ContextAppRouteController, - k7Breadcrumbs, - controllerAs: 'contextAppRoute', - resolve: { - indexPattern: ($route, Promise) => { - const indexPattern = getServices().indexPatterns.get($route.current.params.indexPatternId); - return Promise.props({ ip: indexPattern }); - }, - }, - template: contextAppRouteTemplate, - }); -}); - -function ContextAppRouteController($routeParams, $scope, $route) { - const filterManager = getServices().filterManager; - const indexPattern = $route.current.locals.indexPattern.ip; - const { - startSync: startStateSync, - stopSync: stopStateSync, - appState, - getFilters, - setFilters, - setAppState, - flushToUrl, - } = getState({ - defaultStepSize: getServices().uiSettings.get(CONTEXT_DEFAULT_SIZE_SETTING), - timeFieldName: indexPattern.timeFieldName, - storeInSessionStorage: getServices().uiSettings.get('state:storeInSessionStorage'), - history: getServices().history(), - toasts: getServices().core.notifications.toasts, - }); - this.state = { ...appState.getState() }; - this.anchorId = decodeURIComponent($routeParams.id); - this.indexPattern = indexPattern; - filterManager.setFilters(_.cloneDeep(getFilters())); - startStateSync(); - - // take care of parameter changes in UI - $scope.$watchGroup( - [ - 'contextAppRoute.state.columns', - 'contextAppRoute.state.predecessorCount', - 'contextAppRoute.state.successorCount', - ], - (newValues) => { - const [columns, predecessorCount, successorCount] = newValues; - if (Array.isArray(columns) && predecessorCount >= 0 && successorCount >= 0) { - setAppState({ columns, predecessorCount, successorCount }); - flushToUrl(true); - } - } - ); - // take care of parameter filter changes - const filterObservable = filterManager.getUpdates$().subscribe(() => { - setFilters(filterManager); - $route.reload(); - }); - - $scope.$on('$destroy', () => { - stopStateSync(); - filterObservable.unsubscribe(); - }); -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/NOTES.md b/src/plugins/discover_legacy/public/application/angular/context/NOTES.md deleted file mode 100644 index 046e15fab327..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/NOTES.md +++ /dev/null @@ -1,95 +0,0 @@ -# Discover Context App Implementation Notes - -The implementation of this app is intended to exhibit certain desirable -properties by adhering to a set of *principles*. This document aims to explain -those and the *concepts* employed to achieve that. - - -## Principles - -**Single Source of Truth**: A good user experience depends on the UI displaying -consistent information across the whole page. To achieve this, there should -always be a single source of truth for the application's state. In this -application this is the `ContextAppController::state` object. - -**Unidirectional Data Flow**: While a single state promotes rendering -consistency, it does little to make the state changes easier to reason about. -To avoid having state mutations scattered all over the code, this app -implements a unidirectional data flow architecture. That means that the state -is treated as immutable throughout the application except for actions, which -may modify it to cause angular to re-render and watches to trigger. - -**Unit-Testability**: Creating unit tests for large parts of the UI code is -made easy by expressing the as much of the logic as possible as -side-effect-free functions. The only place where side-effects are allowed are -actions. Due to the nature of AngularJS a certain amount of impure code must be -employed in some cases, e.g. when dealing with the isolate scope bindings in -`ContextAppController`. - -**Loose Coupling**: An attempt was made to couple the parts that make up this -app as loosely as possible. This means using pure functions whenever possible -and isolating the angular directives diligently. To that end, the app has been -implemented as the independent `ContextApp` directive in [app.js](app.js). It -does not access the OpenSearch Dashboards `AppState` directly but communicates only via its -directive properties. The binding of these attributes to the state and thereby -to the route is performed by the `CreateAppRouteController`in -[index.js](index.js). Similarly, the `SizePicker` directive only communicates -with its parent via the passed properties. - - -## Concepts - -To adhere to the principles mentioned above, this app borrows some concepts -from the redux architecture that forms a ciruclar unidirectional data flow: - -``` - - |* create initial state - v - +->+ - | v - | |* state - | v - | |* angular templates render state - | v - | |* angular calls actions in response to user action/system events - | v - | |* actions modify state - | v - +--+ - -``` - -**State**: The state is the single source of truth at -`ContextAppController::state` and may only be modified by actions. - -**Action**: Actions are functions that are called in response to user or system -actions and may modified the state the are bound to via their closure. - - -## Directory Structure - -**index.js**: Defines the route and renders the `` directive, -binding it to the `AppState`. - -**app.js**: Defines the `` directive, that is at the root of the -application. Creates the store, reducer and bound actions/selectors. - -**query**: Exports the actions, reducers and selectors related to the -query status and results. - -**query_parameters**: Exports the actions, reducers and selectors related to -the parameters used to construct the query. - -**components/action_bar**: Defines the `` -directive including its respective styles. - - -**api/anchor.js**: Exports `fetchAnchor()` that creates and executes the -query for the anchor document. - -**api/context.js**: Exports `fetchPredecessors()`, `fetchSuccessors()`, `fetchSurroundingDocs()` that -create and execute the queries for the preceeding and succeeding documents. - -**api/utils**: Exports various functions used to create and transform -queries. diff --git a/src/plugins/discover_legacy/public/application/angular/context/_index.scss b/src/plugins/discover_legacy/public/application/angular/context/_index.scss deleted file mode 100644 index 4ac09e25eb9c..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/_index.scss +++ /dev/null @@ -1,8 +0,0 @@ -// Prefix all styles with "cxt" to avoid conflicts. -// Examples -// cxtChart -// cxtChart__legend -// cxtChart__legend--small -// cxtChart__legend-isLoading - -@import "components/action_bar/index"; diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/_stubs.js b/src/plugins/discover_legacy/public/application/angular/context/api/_stubs.js deleted file mode 100644 index 99b531edfc0b..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/_stubs.js +++ /dev/null @@ -1,112 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 sinon from 'sinon'; -import moment from 'moment'; - -export function createIndexPatternsStub() { - return { - get: sinon.spy((indexPatternId) => - Promise.resolve({ - id: indexPatternId, - isTimeNanosBased: () => false, - popularizeField: () => {}, - }) - ), - }; -} - -/** - * A stubbed search source with a `fetch` method that returns all of `_stubHits`. - */ -export function createSearchSourceStub(hits, timeField) { - const searchSourceStub = { - _stubHits: hits, - _stubTimeField: timeField, - _createStubHit: (timestamp, tiebreaker = 0) => ({ - [searchSourceStub._stubTimeField]: timestamp, - sort: [timestamp, tiebreaker], - }), - }; - - searchSourceStub.setParent = sinon.spy(() => searchSourceStub); - searchSourceStub.setField = sinon.spy(() => searchSourceStub); - - searchSourceStub.getField = sinon.spy((key) => { - const previousSetCall = searchSourceStub.setField.withArgs(key).lastCall; - return previousSetCall ? previousSetCall.args[1] : null; - }); - - searchSourceStub.fetch = sinon.spy(() => - Promise.resolve({ - hits: { - hits: searchSourceStub._stubHits, - total: searchSourceStub._stubHits.length, - }, - }) - ); - - return searchSourceStub; -} - -/** - * A stubbed search source with a `fetch` method that returns a filtered set of `_stubHits`. - */ -export function createContextSearchSourceStub(hits, timeField = '@timestamp') { - const searchSourceStub = createSearchSourceStub(hits, timeField); - - searchSourceStub.fetch = sinon.spy(() => { - const timeField = searchSourceStub._stubTimeField; - const lastQuery = searchSourceStub.setField.withArgs('query').lastCall.args[1]; - const timeRange = lastQuery.query.bool.must.constant_score.filter.range[timeField]; - const lastSort = searchSourceStub.setField.withArgs('sort').lastCall.args[1]; - const sortDirection = lastSort[0][timeField]; - const sortFunction = - sortDirection === 'asc' - ? (first, second) => first[timeField] - second[timeField] - : (first, second) => second[timeField] - first[timeField]; - const filteredHits = searchSourceStub._stubHits - .filter( - (hit) => - moment(hit[timeField]).isSameOrAfter(timeRange.gte) && - moment(hit[timeField]).isSameOrBefore(timeRange.lte) - ) - .sort(sortFunction); - - return Promise.resolve({ - hits: { - hits: filteredHits, - total: filteredHits.length, - }, - }); - }); - - return searchSourceStub; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/anchor.js b/src/plugins/discover_legacy/public/application/angular/context/api/anchor.js deleted file mode 100644 index 599379e128b0..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/anchor.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { i18n } from '@osd/i18n'; - -export function fetchAnchorProvider(indexPatterns, searchSource) { - return async function fetchAnchor(indexPatternId, anchorId, sort) { - const indexPattern = await indexPatterns.get(indexPatternId); - searchSource - .setParent(undefined) - .setField('index', indexPattern) - .setField('version', true) - .setField('size', 1) - .setField('query', { - query: { - constant_score: { - filter: { - ids: { - values: [anchorId], - }, - }, - }, - }, - language: 'lucene', - }) - .setField('sort', sort); - - const response = await searchSource.fetch(); - - if (_.get(response, ['hits', 'total'], 0) < 1) { - throw new Error( - i18n.translate('discover.context.failedToLoadAnchorDocumentErrorDescription', { - defaultMessage: 'Failed to load anchor document.', - }) - ); - } - - return { - ..._.get(response, ['hits', 'hits', 0]), - $$_isAnchor: true, - }; - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/anchor.test.js b/src/plugins/discover_legacy/public/application/angular/context/api/anchor.test.js deleted file mode 100644 index 676aabb5c3b8..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/anchor.test.js +++ /dev/null @@ -1,158 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { createIndexPatternsStub, createSearchSourceStub } from './_stubs'; - -import { fetchAnchorProvider } from './anchor'; - -describe('context app', function () { - describe('function fetchAnchor', function () { - let fetchAnchor; - let searchSourceStub; - - beforeEach(() => { - searchSourceStub = createSearchSourceStub([{ _id: 'hit1' }]); - fetchAnchor = fetchAnchorProvider(createIndexPatternsStub(), searchSourceStub); - }); - - it('should use the `fetch` method of the SearchSource', function () { - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then(() => { - expect(searchSourceStub.fetch.calledOnce).toBe(true); - }); - }); - - it('should configure the SearchSource to not inherit from the implicit root', function () { - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then(() => { - const setParentSpy = searchSourceStub.setParent; - expect(setParentSpy.calledOnce).toBe(true); - expect(setParentSpy.firstCall.args[0]).toBe(undefined); - }); - }); - - it('should set the SearchSource index pattern', function () { - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then(() => { - const setFieldSpy = searchSourceStub.setField; - expect(setFieldSpy.firstCall.args[1].id).toEqual('INDEX_PATTERN_ID'); - }); - }); - - it('should set the SearchSource version flag to true', function () { - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then(() => { - const setVersionSpy = searchSourceStub.setField.withArgs('version'); - expect(setVersionSpy.calledOnce).toBe(true); - expect(setVersionSpy.firstCall.args[1]).toEqual(true); - }); - }); - - it('should set the SearchSource size to 1', function () { - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then(() => { - const setSizeSpy = searchSourceStub.setField.withArgs('size'); - expect(setSizeSpy.calledOnce).toBe(true); - expect(setSizeSpy.firstCall.args[1]).toEqual(1); - }); - }); - - it('should set the SearchSource query to an ids query', function () { - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then(() => { - const setQuerySpy = searchSourceStub.setField.withArgs('query'); - expect(setQuerySpy.calledOnce).toBe(true); - expect(setQuerySpy.firstCall.args[1]).toEqual({ - query: { - constant_score: { - filter: { - ids: { - values: ['id'], - }, - }, - }, - }, - language: 'lucene', - }); - }); - }); - - it('should set the SearchSource sort order', function () { - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then(() => { - const setSortSpy = searchSourceStub.setField.withArgs('sort'); - expect(setSortSpy.calledOnce).toBe(true); - expect(setSortSpy.firstCall.args[1]).toEqual([{ '@timestamp': 'desc' }, { _doc: 'desc' }]); - }); - }); - - it('should reject with an error when no hits were found', function () { - searchSourceStub._stubHits = []; - - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then( - () => { - expect().fail('expected the promise to be rejected'); - }, - (error) => { - expect(error).toBeInstanceOf(Error); - } - ); - }); - - it('should return the first hit after adding an anchor marker', function () { - searchSourceStub._stubHits = [{ property1: 'value1' }, { property2: 'value2' }]; - - return fetchAnchor('INDEX_PATTERN_ID', 'id', [ - { '@timestamp': 'desc' }, - { _doc: 'desc' }, - ]).then((anchorDocument) => { - expect(anchorDocument).toHaveProperty('property1', 'value1'); - expect(anchorDocument).toHaveProperty('$$_isAnchor', true); - }); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/context.predecessors.test.js b/src/plugins/discover_legacy/public/application/angular/context/api/context.predecessors.test.js deleted file mode 100644 index 52ddc2978ad8..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/context.predecessors.test.js +++ /dev/null @@ -1,241 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 moment from 'moment'; -import { get, last } from 'lodash'; -import { createIndexPatternsStub, createContextSearchSourceStub } from './_stubs'; -import { fetchContextProvider } from './context'; -import { setServices } from '../../../../opensearch_dashboards_services'; - -const MS_PER_DAY = 24 * 60 * 60 * 1000; -const ANCHOR_TIMESTAMP = new Date(MS_PER_DAY).toJSON(); -const ANCHOR_TIMESTAMP_3 = new Date(MS_PER_DAY * 3).toJSON(); -const ANCHOR_TIMESTAMP_1000 = new Date(MS_PER_DAY * 1000).toJSON(); -const ANCHOR_TIMESTAMP_3000 = new Date(MS_PER_DAY * 3000).toJSON(); - -describe('context app', function () { - describe('function fetchPredecessors', function () { - let fetchPredecessors; - let mockSearchSource; - - beforeEach(() => { - mockSearchSource = createContextSearchSourceStub([], '@timestamp', MS_PER_DAY * 8); - - setServices({ - data: { - search: { - searchSource: { - create: jest.fn().mockImplementation(() => mockSearchSource), - }, - }, - }, - }); - - fetchPredecessors = ( - indexPatternId, - timeField, - sortDir, - timeValIso, - timeValNr, - tieBreakerField, - tieBreakerValue, - size - ) => { - const anchor = { - _source: { - [timeField]: timeValIso, - }, - sort: [timeValNr, tieBreakerValue], - }; - - return fetchContextProvider(createIndexPatternsStub()).fetchSurroundingDocs( - 'predecessors', - indexPatternId, - anchor, - timeField, - tieBreakerField, - sortDir, - size, - [] - ); - }; - }); - - it('should perform exactly one query when enough hits are returned', function () { - mockSearchSource._stubHits = [ - mockSearchSource._createStubHit(MS_PER_DAY * 3000 + 2), - mockSearchSource._createStubHit(MS_PER_DAY * 3000 + 1), - mockSearchSource._createStubHit(MS_PER_DAY * 3000), - mockSearchSource._createStubHit(MS_PER_DAY * 2000), - mockSearchSource._createStubHit(MS_PER_DAY * 1000), - ]; - - return fetchPredecessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3000, - MS_PER_DAY * 3000, - '_doc', - 0, - 3, - [] - ).then((hits) => { - expect(mockSearchSource.fetch.calledOnce).toBe(true); - expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 3)); - }); - }); - - it('should perform multiple queries with the last being unrestricted when too few hits are returned', function () { - mockSearchSource._stubHits = [ - mockSearchSource._createStubHit(MS_PER_DAY * 3010), - mockSearchSource._createStubHit(MS_PER_DAY * 3002), - mockSearchSource._createStubHit(MS_PER_DAY * 3000), - mockSearchSource._createStubHit(MS_PER_DAY * 2998), - mockSearchSource._createStubHit(MS_PER_DAY * 2990), - ]; - - return fetchPredecessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3000, - MS_PER_DAY * 3000, - '_doc', - 0, - 6, - [] - ).then((hits) => { - const intervals = mockSearchSource.setField.args - .filter(([property]) => property === 'query') - .map(([, { query }]) => - get(query, ['bool', 'must', 'constant_score', 'filter', 'range', '@timestamp']) - ); - - expect( - intervals.every(({ gte, lte }) => (gte && lte ? moment(gte).isBefore(lte) : true)) - ).toBe(true); - // should have started at the given time - expect(intervals[0].gte).toEqual(moment(MS_PER_DAY * 3000).toISOString()); - // should have ended with a half-open interval - expect(Object.keys(last(intervals))).toEqual(['format', 'gte']); - expect(intervals.length).toBeGreaterThan(1); - - expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 3)); - }); - }); - - it('should perform multiple queries until the expected hit count is returned', function () { - mockSearchSource._stubHits = [ - mockSearchSource._createStubHit(MS_PER_DAY * 1700), - mockSearchSource._createStubHit(MS_PER_DAY * 1200), - mockSearchSource._createStubHit(MS_PER_DAY * 1100), - mockSearchSource._createStubHit(MS_PER_DAY * 1000), - ]; - - return fetchPredecessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_1000, - MS_PER_DAY * 1000, - '_doc', - 0, - 3, - [] - ).then((hits) => { - const intervals = mockSearchSource.setField.args - .filter(([property]) => property === 'query') - .map(([, { query }]) => - get(query, ['bool', 'must', 'constant_score', 'filter', 'range', '@timestamp']) - ); - - // should have started at the given time - expect(intervals[0].gte).toEqual(moment(MS_PER_DAY * 1000).toISOString()); - // should have stopped before reaching MS_PER_DAY * 1700 - expect(moment(last(intervals).lte).valueOf()).toBeLessThan(MS_PER_DAY * 1700); - expect(intervals.length).toBeGreaterThan(1); - expect(hits).toEqual(mockSearchSource._stubHits.slice(-3)); - }); - }); - - it('should return an empty array when no hits were found', function () { - return fetchPredecessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3, - MS_PER_DAY * 3, - '_doc', - 0, - 3, - [] - ).then((hits) => { - expect(hits).toEqual([]); - }); - }); - - it('should configure the SearchSource to not inherit from the implicit root', function () { - return fetchPredecessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3, - MS_PER_DAY * 3, - '_doc', - 0, - 3, - [] - ).then(() => { - const setParentSpy = mockSearchSource.setParent; - expect(setParentSpy.alwaysCalledWith(undefined)).toBe(true); - expect(setParentSpy.called).toBe(true); - }); - }); - - it('should set the tiebreaker sort order to the opposite as the time field', function () { - return fetchPredecessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP, - MS_PER_DAY, - '_doc', - 0, - 3, - [] - ).then(() => { - expect( - mockSearchSource.setField.calledWith('sort', [{ '@timestamp': 'asc' }, { _doc: 'asc' }]) - ).toBe(true); - }); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/context.successors.test.js b/src/plugins/discover_legacy/public/application/angular/context/api/context.successors.test.js deleted file mode 100644 index 7086495e29e0..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/context.successors.test.js +++ /dev/null @@ -1,245 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 moment from 'moment'; -import { get, last } from 'lodash'; - -import { createIndexPatternsStub, createContextSearchSourceStub } from './_stubs'; -import { setServices } from '../../../../opensearch_dashboards_services'; - -import { fetchContextProvider } from './context'; - -const MS_PER_DAY = 24 * 60 * 60 * 1000; -const ANCHOR_TIMESTAMP = new Date(MS_PER_DAY).toJSON(); -const ANCHOR_TIMESTAMP_3 = new Date(MS_PER_DAY * 3).toJSON(); -const ANCHOR_TIMESTAMP_3000 = new Date(MS_PER_DAY * 3000).toJSON(); - -describe('context app', function () { - describe('function fetchSuccessors', function () { - let fetchSuccessors; - let mockSearchSource; - - beforeEach(() => { - mockSearchSource = createContextSearchSourceStub([], '@timestamp'); - - setServices({ - data: { - search: { - searchSource: { - create: jest.fn().mockImplementation(() => mockSearchSource), - }, - }, - }, - }); - - fetchSuccessors = ( - indexPatternId, - timeField, - sortDir, - timeValIso, - timeValNr, - tieBreakerField, - tieBreakerValue, - size - ) => { - const anchor = { - _source: { - [timeField]: timeValIso, - }, - sort: [timeValNr, tieBreakerValue], - }; - - return fetchContextProvider(createIndexPatternsStub()).fetchSurroundingDocs( - 'successors', - indexPatternId, - anchor, - timeField, - tieBreakerField, - sortDir, - size, - [] - ); - }; - }); - - it('should perform exactly one query when enough hits are returned', function () { - mockSearchSource._stubHits = [ - mockSearchSource._createStubHit(MS_PER_DAY * 5000), - mockSearchSource._createStubHit(MS_PER_DAY * 4000), - mockSearchSource._createStubHit(MS_PER_DAY * 3000), - mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 1), - mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 2), - ]; - - return fetchSuccessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3000, - MS_PER_DAY * 3000, - '_doc', - 0, - 3, - [] - ).then((hits) => { - expect(mockSearchSource.fetch.calledOnce).toBe(true); - expect(hits).toEqual(mockSearchSource._stubHits.slice(-3)); - }); - }); - - it('should perform multiple queries with the last being unrestricted when too few hits are returned', function () { - mockSearchSource._stubHits = [ - mockSearchSource._createStubHit(MS_PER_DAY * 3010), - mockSearchSource._createStubHit(MS_PER_DAY * 3002), - mockSearchSource._createStubHit(MS_PER_DAY * 3000), - mockSearchSource._createStubHit(MS_PER_DAY * 2998), - mockSearchSource._createStubHit(MS_PER_DAY * 2990), - ]; - - return fetchSuccessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3000, - MS_PER_DAY * 3000, - '_doc', - 0, - 6, - [] - ).then((hits) => { - const intervals = mockSearchSource.setField.args - .filter(([property]) => property === 'query') - .map(([, { query }]) => - get(query, ['bool', 'must', 'constant_score', 'filter', 'range', '@timestamp']) - ); - - expect( - intervals.every(({ gte, lte }) => (gte && lte ? moment(gte).isBefore(lte) : true)) - ).toBe(true); - // should have started at the given time - expect(intervals[0].lte).toEqual(moment(MS_PER_DAY * 3000).toISOString()); - // should have ended with a half-open interval - expect(Object.keys(last(intervals))).toEqual(['format', 'lte']); - expect(intervals.length).toBeGreaterThan(1); - - expect(hits).toEqual(mockSearchSource._stubHits.slice(-3)); - }); - }); - - it('should perform multiple queries until the expected hit count is returned', function () { - mockSearchSource._stubHits = [ - mockSearchSource._createStubHit(MS_PER_DAY * 3000), - mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 1), - mockSearchSource._createStubHit(MS_PER_DAY * 3000 - 2), - mockSearchSource._createStubHit(MS_PER_DAY * 2800), - mockSearchSource._createStubHit(MS_PER_DAY * 2200), - mockSearchSource._createStubHit(MS_PER_DAY * 1000), - ]; - - return fetchSuccessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3000, - MS_PER_DAY * 3000, - '_doc', - 0, - 4, - [] - ).then((hits) => { - const intervals = mockSearchSource.setField.args - .filter(([property]) => property === 'query') - .map(([, { query }]) => - get(query, ['bool', 'must', 'constant_score', 'filter', 'range', '@timestamp']) - ); - - // should have started at the given time - expect(intervals[0].lte).toEqual(moment(MS_PER_DAY * 3000).toISOString()); - // should have stopped before reaching MS_PER_DAY * 2200 - expect(moment(last(intervals).gte).valueOf()).toBeGreaterThan(MS_PER_DAY * 2200); - expect(intervals.length).toBeGreaterThan(1); - - expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 4)); - }); - }); - - it('should return an empty array when no hits were found', function () { - return fetchSuccessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3, - MS_PER_DAY * 3, - '_doc', - 0, - 3, - [] - ).then((hits) => { - expect(hits).toEqual([]); - }); - }); - - it('should configure the SearchSource to not inherit from the implicit root', function () { - return fetchSuccessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP_3, - MS_PER_DAY * 3, - '_doc', - 0, - 3, - [] - ).then(() => { - const setParentSpy = mockSearchSource.setParent; - expect(setParentSpy.alwaysCalledWith(undefined)).toBe(true); - expect(setParentSpy.called).toBe(true); - }); - }); - - it('should set the tiebreaker sort order to the same as the time field', function () { - return fetchSuccessors( - 'INDEX_PATTERN_ID', - '@timestamp', - 'desc', - ANCHOR_TIMESTAMP, - MS_PER_DAY, - '_doc', - 0, - 3, - [] - ).then(() => { - expect( - mockSearchSource.setField.calledWith('sort', [{ '@timestamp': 'desc' }, { _doc: 'desc' }]) - ).toBe(true); - }); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/context.ts b/src/plugins/discover_legacy/public/application/angular/context/api/context.ts deleted file mode 100644 index 046438f08339..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/context.ts +++ /dev/null @@ -1,137 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { Filter, IndexPatternsContract, IndexPattern } from 'src/plugins/data/public'; -import { reverseSortDir, SortDirection } from './utils/sorting'; -import { extractNanos, convertIsoToMillis } from './utils/date_conversion'; -import { fetchHitsInInterval } from './utils/fetch_hits_in_interval'; -import { generateIntervals } from './utils/generate_intervals'; -import { getOpenSearchQuerySearchAfter } from './utils/get_opensearch_query_search_after'; -import { getOpenSearchQuerySort } from './utils/get_opensearch_query_sort'; -import { getServices } from '../../../../opensearch_dashboards_services'; - -export type SurrDocType = 'successors' | 'predecessors'; -export interface OpenSearchHitRecord { - fields: Record; - sort: number[]; - _source: Record; - _id: string; -} -export type OpenSearchHitRecordList = OpenSearchHitRecord[]; - -const DAY_MILLIS = 24 * 60 * 60 * 1000; - -// look from 1 day up to 10000 days into the past and future -const LOOKUP_OFFSETS = [0, 1, 7, 30, 365, 10000].map((days) => days * DAY_MILLIS); - -function fetchContextProvider(indexPatterns: IndexPatternsContract) { - return { - fetchSurroundingDocs, - }; - - /** - * Fetch successor or predecessor documents of a given anchor document - * - * @param {SurrDocType} type - `successors` or `predecessors` - * @param {string} indexPatternId - * @param {OpenSearchHitRecord} anchor - anchor record - * @param {string} timeField - name of the timefield, that's sorted on - * @param {string} tieBreakerField - name of the tie breaker, the 2nd sort field - * @param {SortDirection} sortDir - direction of sorting - * @param {number} size - number of records to retrieve - * @param {Filter[]} filters - to apply in the query - * @returns {Promise} - */ - async function fetchSurroundingDocs( - type: SurrDocType, - indexPatternId: string, - anchor: OpenSearchHitRecord, - timeField: string, - tieBreakerField: string, - sortDir: SortDirection, - size: number, - filters: Filter[] - ) { - if (typeof anchor !== 'object' || anchor === null || !size) { - return []; - } - const indexPattern = await indexPatterns.get(indexPatternId); - const searchSource = await createSearchSource(indexPattern, filters); - const sortDirToApply = type === 'successors' ? sortDir : reverseSortDir(sortDir); - - const nanos = indexPattern.isTimeNanosBased() ? extractNanos(anchor._source[timeField]) : ''; - const timeValueMillis = - nanos !== '' ? convertIsoToMillis(anchor._source[timeField]) : anchor.sort[0]; - - const intervals = generateIntervals(LOOKUP_OFFSETS, timeValueMillis, type, sortDir); - let documents: OpenSearchHitRecordList = []; - - for (const interval of intervals) { - const remainingSize = size - documents.length; - - if (remainingSize <= 0) { - break; - } - - const searchAfter = getOpenSearchQuerySearchAfter(type, documents, timeField, anchor, nanos); - - const sort = getOpenSearchQuerySort(timeField, tieBreakerField, sortDirToApply); - - const hits = await fetchHitsInInterval( - searchSource, - timeField, - sort, - sortDirToApply, - interval, - searchAfter, - remainingSize, - nanos, - anchor._id - ); - - documents = - type === 'successors' ? [...documents, ...hits] : [...hits.slice().reverse(), ...documents]; - } - - return documents; - } - - async function createSearchSource(indexPattern: IndexPattern, filters: Filter[]) { - const { data } = getServices(); - - const searchSource = await data.search.searchSource.create(); - return searchSource - .setParent(undefined) - .setField('index', indexPattern) - .setField('filter', filters); - } -} - -export { fetchContextProvider }; diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/utils/date_conversion.test.ts b/src/plugins/discover_legacy/public/application/angular/context/api/utils/date_conversion.test.ts deleted file mode 100644 index fe1a18bf938f..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/utils/date_conversion.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { extractNanos } from './date_conversion'; - -describe('function extractNanos', function () { - test('extract nanos of 2014-01-01', function () { - expect(extractNanos('2014-01-01')).toBe('000000000'); - }); - test('extract nanos of 2014-01-01T12:12:12.234Z', function () { - expect(extractNanos('2014-01-01T12:12:12.234Z')).toBe('234000000'); - }); - test('extract nanos of 2014-01-01T12:12:12.234123321Z', function () { - expect(extractNanos('2014-01-01T12:12:12.234123321Z')).toBe('234123321'); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/utils/date_conversion.ts b/src/plugins/discover_legacy/public/application/angular/context/api/utils/date_conversion.ts deleted file mode 100644 index 8f4bfb30375d..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/utils/date_conversion.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 moment from 'moment'; -/** - * extract nanoseconds if available in ISO timestamp - * returns the nanos as string like this: - * 9ns -> 000000009 - * 10000ns -> 0000010000 - * returns 000000000 for invalid timestamps or timestamps with just date - **/ -export function extractNanos(timeFieldValue: string = ''): string { - const fieldParts = timeFieldValue.split('.'); - const fractionSeconds = fieldParts.length === 2 ? fieldParts[1].replace('Z', '') : ''; - return fractionSeconds.length !== 9 ? fractionSeconds.padEnd(9, '0') : fractionSeconds; -} - -/** - * convert an iso formatted string to number of milliseconds since - * 1970-01-01T00:00:00.000Z - * @param {string} isoValue - * @returns {number} - */ -export function convertIsoToMillis(isoValue: string): number { - const date = new Date(isoValue); - return date.getTime(); -} -/** - * the given time value in milliseconds is converted to a ISO formatted string - * if nanosValue is provided, the given value replaces the fractional seconds part - * of the formated string since moment.js doesn't support formatting timestamps - * with a higher precision then microseconds - * The browser rounds date nanos values: - * 2019-09-18T06:50:12.999999999 -> browser rounds to 1568789413000000000 - * 2019-09-18T06:50:59.999999999 -> browser rounds to 1568789460000000000 - * 2017-12-31T23:59:59.999999999 -> browser rounds 1514761199999999999 to 1514761200000000000 - */ -export function convertTimeValueToIso(timeValueMillis: number, nanosValue: string): string | null { - if (!timeValueMillis) { - return null; - } - const isoString = moment(timeValueMillis).toISOString(); - if (!isoString) { - return null; - } else if (nanosValue !== '') { - return `${isoString.substring(0, isoString.length - 4)}${nanosValue}Z`; - } - return isoString; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/utils/fetch_hits_in_interval.ts b/src/plugins/discover_legacy/public/application/angular/context/api/utils/fetch_hits_in_interval.ts deleted file mode 100644 index 262b64ba8c15..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/utils/fetch_hits_in_interval.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { - ISearchSource, - OpenSearchQuerySortValue, - SortDirection, -} from '../../../../../../../data/public'; -import { convertTimeValueToIso } from './date_conversion'; -import { OpenSearchHitRecordList, OpenSearchHitRecord } from '../context'; -import { IntervalValue } from './generate_intervals'; -import { OpenSearchQuerySearchAfter } from './get_opensearch_query_search_after'; - -interface RangeQuery { - format: string; - lte?: string | null; - gte?: string | null; -} - -/** - * Fetch the hits between a given `interval` up to a maximum of `maxCount` documents. - * The documents are sorted by `sort` - * - * The `searchSource` is assumed to have the appropriate index pattern - * and filters set. - */ -export async function fetchHitsInInterval( - searchSource: ISearchSource, - timeField: string, - sort: [OpenSearchQuerySortValue, OpenSearchQuerySortValue], - sortDir: SortDirection, - interval: IntervalValue[], - searchAfter: OpenSearchQuerySearchAfter, - maxCount: number, - nanosValue: string, - anchorId: string -): Promise { - const range: RangeQuery = { - format: 'strict_date_optional_time', - }; - const [start, stop] = interval; - - if (start) { - range[sortDir === SortDirection.asc ? 'gte' : 'lte'] = convertTimeValueToIso(start, nanosValue); - } - - if (stop) { - range[sortDir === SortDirection.asc ? 'lte' : 'gte'] = convertTimeValueToIso(stop, nanosValue); - } - const response = await searchSource - .setField('size', maxCount) - .setField('query', { - query: { - bool: { - must: { - constant_score: { - filter: { - range: { - [timeField]: range, - }, - }, - }, - }, - must_not: { - ids: { - values: [anchorId], - }, - }, - }, - }, - language: 'lucene', - }) - .setField('searchAfter', searchAfter) - .setField('sort', sort) - .setField('version', true) - .fetch(); - - // TODO: There's a difference in the definition of SearchResponse and OpenSearchHitRecord - return ((response.hits?.hits as unknown) as OpenSearchHitRecord[]) || []; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/utils/generate_intervals.ts b/src/plugins/discover_legacy/public/application/angular/context/api/utils/generate_intervals.ts deleted file mode 100644 index fda2e23eb234..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/utils/generate_intervals.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { SortDirection } from '../../../../../../../data/public'; - -export type IntervalValue = number | null; - -/** - * Generate a sequence of pairs from the iterable that looks like - * `[[x_0, x_1], [x_1, x_2], [x_2, x_3], ..., [x_(n-1), x_n]]`. - */ -export function* asPairs(iterable: Iterable): IterableIterator { - let currentPair: IntervalValue[] = []; - for (const value of iterable) { - currentPair = [...currentPair, value].slice(-2); - if (currentPair.length === 2) { - yield currentPair; - } - } -} - -/** - * Returns a iterable containing intervals `[start,end]` for OpenSearch date range queries - * depending on type (`successors` or `predecessors`) and sort (`asc`, `desc`) these are ascending or descending intervals. - */ -export function generateIntervals( - offsets: number[], - startTime: number, - type: string, - sort: SortDirection -): IterableIterator { - const offsetSign = - (sort === SortDirection.asc && type === 'successors') || - (sort === SortDirection.desc && type === 'predecessors') - ? 1 - : -1; - // ending with `null` opens the last interval - return asPairs([...offsets.map((offset) => startTime + offset * offsetSign), null]); -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/utils/get_opensearch_query_search_after.ts b/src/plugins/discover_legacy/public/application/angular/context/api/utils/get_opensearch_query_search_after.ts deleted file mode 100644 index eb6a5af565ba..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/utils/get_opensearch_query_search_after.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { SurrDocType, OpenSearchHitRecordList, OpenSearchHitRecord } from '../context'; - -export type OpenSearchQuerySearchAfter = [string | number, string | number]; - -/** - * Get the searchAfter query value for opensearch - * When there are already documents available, which means successors or predecessors - * were already fetched, the new searchAfter for the next fetch has to be the sort value - * of the first (prececessor), or last (successor) of the list - */ -export function getOpenSearchQuerySearchAfter( - type: SurrDocType, - documents: OpenSearchHitRecordList, - timeFieldName: string, - anchor: OpenSearchHitRecord, - nanoSeconds: string -): OpenSearchQuerySearchAfter { - if (documents.length) { - // already surrounding docs -> first or last record is used - const afterTimeRecIdx = type === 'successors' && documents.length ? documents.length - 1 : 0; - const afterTimeDoc = documents[afterTimeRecIdx]; - const afterTimeValue = nanoSeconds ? afterTimeDoc._source[timeFieldName] : afterTimeDoc.sort[0]; - return [afterTimeValue, afterTimeDoc.sort[1]]; - } - // if data_nanos adapt timestamp value for sorting, since numeric value was rounded by browser - // OpenSearch search_after also works when number is provided as string - return [nanoSeconds ? anchor._source[timeFieldName] : anchor.sort[0], anchor.sort[1]]; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/utils/get_opensearch_query_sort.ts b/src/plugins/discover_legacy/public/application/angular/context/api/utils/get_opensearch_query_sort.ts deleted file mode 100644 index 30c4888fa438..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/utils/get_opensearch_query_sort.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { - OpenSearchQuerySortValue, - SortDirection, -} from '../../../../../opensearch_dashboards_services'; - -/** - * Returns `OpenSearchQuerySort` which is used to sort records in the OpenSearch query - * https://opensearch.org/docs/latest/opensearch/ux/#sort-results - * @param timeField - * @param tieBreakerField - * @param sortDir - */ -export function getOpenSearchQuerySort( - timeField: string, - tieBreakerField: string, - sortDir: SortDirection -): [OpenSearchQuerySortValue, OpenSearchQuerySortValue] { - return [{ [timeField]: sortDir }, { [tieBreakerField]: sortDir }]; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/utils/sorting.test.ts b/src/plugins/discover_legacy/public/application/angular/context/api/utils/sorting.test.ts deleted file mode 100644 index 6944591d40cd..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/utils/sorting.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { reverseSortDir, SortDirection } from './sorting'; - -describe('function reverseSortDir', function () { - test('reverse a given sort direction', function () { - expect(reverseSortDir(SortDirection.asc)).toBe(SortDirection.desc); - expect(reverseSortDir(SortDirection.desc)).toBe(SortDirection.asc); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context/api/utils/sorting.ts b/src/plugins/discover_legacy/public/application/angular/context/api/utils/sorting.ts deleted file mode 100644 index 52b6df12e467..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/api/utils/sorting.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { IndexPattern } from '../../../../../opensearch_dashboards_services'; - -export enum SortDirection { - asc = 'asc', - desc = 'desc', -} - -/** - * The list of field names that are allowed for sorting, but not included in - * index pattern fields. - */ -const META_FIELD_NAMES: string[] = ['_seq_no', '_doc', '_uid']; - -/** - * Returns a field from the intersection of the set of sortable fields in the - * given index pattern and a given set of candidate field names. - */ -export function getFirstSortableField(indexPattern: IndexPattern, fieldNames: string[]) { - const sortableFields = fieldNames.filter( - (fieldName) => - META_FIELD_NAMES.includes(fieldName) || - // @ts-ignore - (indexPattern.fields.getByName(fieldName) || { sortable: false }).sortable - ); - return sortableFields[0]; -} - -/** - * Return the reversed sort direction. - */ -export function reverseSortDir(sortDirection: SortDirection) { - return sortDirection === SortDirection.asc ? SortDirection.desc : SortDirection.asc; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/_action_bar.scss b/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/_action_bar.scss deleted file mode 100644 index da0911c3a452..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/_action_bar.scss +++ /dev/null @@ -1,10 +0,0 @@ -.cxtSizePicker { - text-align: center; - width: $euiSize * 5; - - &::-webkit-outer-spin-button, - &::-webkit-inner-spin-button { - appearance: none; // Hide increment and decrement buttons for type="number" input. - margin: 0; - } -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/_index.scss b/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/_index.scss deleted file mode 100644 index 40a446220577..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import "action_bar"; diff --git a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar.test.tsx b/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar.test.tsx deleted file mode 100644 index 2f7cc40b7d9a..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar.test.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ActionBar, ActionBarProps } from './action_bar'; -import { findTestSubject } from 'test_utils/helpers'; -import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE } from '../../query_parameters/constants'; - -describe('Test Discover Context ActionBar for successor | predecessor records', () => { - ['successors', 'predecessors'].forEach((type) => { - const onChangeCount = jest.fn(); - const props = { - defaultStepSize: 5, - docCount: 20, - docCountAvailable: 0, - isDisabled: false, - isLoading: false, - onChangeCount, - type, - } as ActionBarProps; - const wrapper = mountWithIntl(); - - const input = findTestSubject(wrapper, `${type}CountPicker`); - const btn = findTestSubject(wrapper, `${type}LoadMoreButton`); - - test(`${type}: Load button click`, () => { - btn.simulate('click'); - expect(onChangeCount).toHaveBeenCalledWith(25); - }); - - test(`${type}: Load button click doesnt submit when MAX_CONTEXT_SIZE was reached`, () => { - onChangeCount.mockClear(); - input.simulate('change', { target: { valueAsNumber: MAX_CONTEXT_SIZE } }); - btn.simulate('click'); - expect(onChangeCount).toHaveBeenCalledTimes(0); - }); - - test(`${type}: Count input change submits on blur`, () => { - input.simulate('change', { target: { valueAsNumber: 123 } }); - input.simulate('blur'); - expect(onChangeCount).toHaveBeenCalledWith(123); - }); - - test(`${type}: Count input change submits on return`, () => { - input.simulate('change', { target: { valueAsNumber: 124 } }); - input.simulate('submit'); - expect(onChangeCount).toHaveBeenCalledWith(124); - }); - - test(`${type}: Count input doesnt submits values higher than MAX_CONTEXT_SIZE `, () => { - onChangeCount.mockClear(); - input.simulate('change', { target: { valueAsNumber: MAX_CONTEXT_SIZE + 1 } }); - input.simulate('submit'); - expect(onChangeCount).toHaveBeenCalledTimes(0); - }); - - test(`${type}: Count input doesnt submits values lower than MIN_CONTEXT_SIZE `, () => { - onChangeCount.mockClear(); - input.simulate('change', { target: { valueAsNumber: MIN_CONTEXT_SIZE - 1 } }); - input.simulate('submit'); - expect(onChangeCount).toHaveBeenCalledTimes(0); - }); - - test(`${type}: Warning about limitation of additional records`, () => { - if (type === 'predecessors') { - expect(findTestSubject(wrapper, 'predecessorsWarningMsg').text()).toBe( - 'No documents newer than the anchor could be found.' - ); - } else { - expect(findTestSubject(wrapper, 'successorsWarningMsg').text()).toBe( - 'No documents older than the anchor could be found.' - ); - } - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar.tsx b/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar.tsx deleted file mode 100644 index 8a4b0b308047..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar.tsx +++ /dev/null @@ -1,182 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { useState } from 'react'; -import { i18n } from '@osd/i18n'; -import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; -import { - EuiButtonEmpty, - EuiFieldNumber, - EuiFlexGroup, - EuiFlexItem, - EuiFormRow, - EuiSpacer, -} from '@elastic/eui'; -import { ActionBarWarning } from './action_bar_warning'; -import { SurrDocType } from '../../api/context'; -import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE } from '../../query_parameters/constants'; - -export interface ActionBarProps { - /** - * the number of documents fetched initially and added when the load button is clicked - */ - defaultStepSize: number; - /** - * the number of docs to be displayed - */ - docCount: number; - /** - * the number of documents that are available - * display warning when it's lower than docCount - */ - docCountAvailable: number; - /** - * is true while the anchor record is fetched - */ - isDisabled: boolean; - /** - * is true when list entries are fetched - */ - isLoading: boolean; - /** - * is triggered when the input containing count is changed - * @param count - */ - onChangeCount: (count: number) => void; - /** - * can be `predecessors` or `successors`, usage in context: - * predecessors action bar + records (these are newer records) - * anchor record - * successors records + action bar (these are older records) - */ - type: SurrDocType; -} - -export function ActionBar({ - defaultStepSize, - docCount, - docCountAvailable, - isDisabled, - isLoading, - onChangeCount, - type, -}: ActionBarProps) { - const showWarning = !isDisabled && !isLoading && docCountAvailable < docCount; - const isSuccessor = type === 'successors'; - const [newDocCount, setNewDocCount] = useState(docCount); - const isValid = (value: number) => value >= MIN_CONTEXT_SIZE && value <= MAX_CONTEXT_SIZE; - const onSubmit = (ev: React.FormEvent) => { - ev.preventDefault(); - if (newDocCount !== docCount && isValid(newDocCount)) { - onChangeCount(newDocCount); - } - }; - - return ( - -
- {isSuccessor && } - {isSuccessor && showWarning && ( - - )} - {isSuccessor && showWarning && } - - - { - const value = newDocCount + defaultStepSize; - if (isValid(value)) { - setNewDocCount(value); - onChangeCount(value); - } - }} - flush="right" - > - - - - - - { - setNewDocCount(ev.target.valueAsNumber); - }} - onBlur={() => { - if (newDocCount !== docCount && isValid(newDocCount)) { - onChangeCount(newDocCount); - } - }} - type="number" - value={newDocCount >= 0 ? newDocCount : ''} - /> - - - - - {isSuccessor ? ( - - ) : ( - - )} - - - - {!isSuccessor && showWarning && ( - - )} - {!isSuccessor && } - -
- ); -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar_directive.ts b/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar_directive.ts deleted file mode 100644 index 3aa62e72353e..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar_directive.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getAngularModule } from '../../../../../opensearch_dashboards_services'; -import { ActionBar } from './action_bar'; - -getAngularModule().directive('contextActionBar', function (reactDirective: any) { - return reactDirective(ActionBar); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar_warning.tsx b/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar_warning.tsx deleted file mode 100644 index cfdc3cc0c8cc..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/action_bar_warning.tsx +++ /dev/null @@ -1,84 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { FormattedMessage } from '@osd/i18n/react'; -import { EuiCallOut } from '@elastic/eui'; -import { SurrDocType } from '../../api/context'; - -export function ActionBarWarning({ docCount, type }: { docCount: number; type: SurrDocType }) { - if (type === 'predecessors') { - return ( - - ) : ( - - ) - } - size="s" - /> - ); - } - - return ( - - ) : ( - - ) - } - size="s" - /> - ); -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/index.ts b/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/index.ts deleted file mode 100644 index 1e3799d2121a..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/components/action_bar/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 './action_bar_directive'; diff --git a/src/plugins/discover_legacy/public/application/angular/context/helpers/call_after_bindings_workaround.js b/src/plugins/discover_legacy/public/application/angular/context/helpers/call_after_bindings_workaround.js deleted file mode 100644 index 455cc57b3d4d..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/helpers/call_after_bindings_workaround.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -/** - * WHAT NEEDS THIS WORKAROUND? - * =========================== - * Any directive that meets all of the following criteria: - * - uses isolate scope bindings - * - sets `bindToController: true` - * - synchronously accesses the bound values in the controller constructor - * - * - * - * HOW DO I GET RID OF IT? - * ======================= - * The quick band-aid solution: - * Wrap your constructor logic so it doesn't access bound values - * synchronously. This can have subtle bugs which is why I didn't - * just wrap all of the offenders in $timeout() and made this - * workaround instead. - * - * The more complete solution: - * Use the new component lifecycle methods, like `$onInit()`, to access - * bindings immediately after the constructor is called, which shouldn't - * have any observable effect outside of the constructor. - * - * NOTE: `$onInit()` is not dependency injected, if you need controller specific - * dependencies like `$scope` then you're probably using watchers and should - * take a look at the new one-way data flow facilities available to - * directives/components: - * - * https://docs.angularjs.org/guide/component#component-based-application-architecture - * - */ - -export function callAfterBindingsWorkaround(constructor) { - return function InitAfterBindingsWrapper($injector, $attrs, $element, $scope, $transclude) { - this.$onInit = () => { - $injector.invoke(constructor, this, { - $attrs, - $element, - $scope, - $transclude, - }); - }; - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/query/actions.js b/src/plugins/discover_legacy/public/application/angular/context/query/actions.js deleted file mode 100644 index d4b4f9ba9977..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query/actions.js +++ /dev/null @@ -1,203 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { i18n } from '@osd/i18n'; -import React from 'react'; -import { getServices } from '../../../../opensearch_dashboards_services'; - -import { fetchAnchorProvider } from '../api/anchor'; -import { fetchContextProvider } from '../api/context'; -import { getQueryParameterActions } from '../query_parameters'; -import { FAILURE_REASONS, LOADING_STATUS } from './constants'; -import { MarkdownSimple } from '../../../../../../opensearch_dashboards_react/public'; - -export function QueryActionsProvider(Promise) { - const { filterManager, indexPatterns, data } = getServices(); - const fetchAnchor = fetchAnchorProvider(indexPatterns, data.search.searchSource.createEmpty()); - const { fetchSurroundingDocs } = fetchContextProvider(indexPatterns); - const { setPredecessorCount, setQueryParameters, setSuccessorCount } = getQueryParameterActions( - filterManager, - indexPatterns - ); - - const setFailedStatus = (state) => (subject, details = {}) => - (state.loadingStatus[subject] = { - status: LOADING_STATUS.FAILED, - reason: FAILURE_REASONS.UNKNOWN, - ...details, - }); - - const setLoadedStatus = (state) => (subject) => - (state.loadingStatus[subject] = { - status: LOADING_STATUS.LOADED, - }); - - const setLoadingStatus = (state) => (subject) => - (state.loadingStatus[subject] = { - status: LOADING_STATUS.LOADING, - }); - - const fetchAnchorRow = (state) => () => { - const { - queryParameters: { indexPatternId, anchorId, sort, tieBreakerField }, - } = state; - - if (!tieBreakerField) { - return Promise.reject( - setFailedStatus(state)('anchor', { - reason: FAILURE_REASONS.INVALID_TIEBREAKER, - }) - ); - } - - setLoadingStatus(state)('anchor'); - - return Promise.try(() => - fetchAnchor(indexPatternId, anchorId, [_.fromPairs([sort]), { [tieBreakerField]: sort[1] }]) - ).then( - (anchorDocument) => { - setLoadedStatus(state)('anchor'); - state.rows.anchor = anchorDocument; - return anchorDocument; - }, - (error) => { - setFailedStatus(state)('anchor', { error }); - getServices().toastNotifications.addDanger({ - title: i18n.translate('discover.context.unableToLoadAnchorDocumentDescription', { - defaultMessage: 'Unable to load the anchor document', - }), - text: {error.message}, - }); - throw error; - } - ); - }; - - const fetchSurroundingRows = (type, state) => { - const { - queryParameters: { indexPatternId, sort, tieBreakerField }, - rows: { anchor }, - } = state; - const filters = getServices().filterManager.getFilters(); - - const count = - type === 'successors' - ? state.queryParameters.successorCount - : state.queryParameters.predecessorCount; - - if (!tieBreakerField) { - return Promise.reject( - setFailedStatus(state)(type, { - reason: FAILURE_REASONS.INVALID_TIEBREAKER, - }) - ); - } - - setLoadingStatus(state)(type); - const [sortField, sortDir] = sort; - - return Promise.try(() => - fetchSurroundingDocs( - type, - indexPatternId, - anchor, - sortField, - tieBreakerField, - sortDir, - count, - filters - ) - ).then( - (documents) => { - setLoadedStatus(state)(type); - state.rows[type] = documents; - return documents; - }, - (error) => { - setFailedStatus(state)(type, { error }); - getServices().toastNotifications.addDanger({ - title: i18n.translate('discover.context.unableToLoadDocumentDescription', { - defaultMessage: 'Unable to load documents', - }), - text: {error.message}, - }); - throw error; - } - ); - }; - - const fetchContextRows = (state) => () => - Promise.all([ - fetchSurroundingRows('predecessors', state), - fetchSurroundingRows('successors', state), - ]); - - const fetchAllRows = (state) => () => - Promise.try(fetchAnchorRow(state)).then(fetchContextRows(state)); - - const fetchContextRowsWithNewQueryParameters = (state) => (queryParameters) => { - setQueryParameters(state)(queryParameters); - return fetchContextRows(state)(); - }; - - const fetchAllRowsWithNewQueryParameters = (state) => (queryParameters) => { - setQueryParameters(state)(queryParameters); - return fetchAllRows(state)(); - }; - - const fetchGivenPredecessorRows = (state) => (count) => { - setPredecessorCount(state)(count); - return fetchSurroundingRows('predecessors', state); - }; - - const fetchGivenSuccessorRows = (state) => (count) => { - setSuccessorCount(state)(count); - return fetchSurroundingRows('successors', state); - }; - - const setAllRows = (state) => (predecessorRows, anchorRow, successorRows) => - (state.rows.all = [ - ...(predecessorRows || []), - ...(anchorRow ? [anchorRow] : []), - ...(successorRows || []), - ]); - - return { - fetchAllRows, - fetchAllRowsWithNewQueryParameters, - fetchAnchorRow, - fetchContextRows, - fetchContextRowsWithNewQueryParameters, - fetchGivenPredecessorRows, - fetchGivenSuccessorRows, - setAllRows, - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/query/constants.js b/src/plugins/discover_legacy/public/application/angular/context/query/constants.js deleted file mode 100644 index 99039d463b5b..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query/constants.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 FAILURE_REASONS = { - UNKNOWN: 'unknown', - INVALID_TIEBREAKER: 'invalid_tiebreaker', -}; - -export const LOADING_STATUS = { - FAILED: 'failed', - LOADED: 'loaded', - LOADING: 'loading', - UNINITIALIZED: 'uninitialized', -}; diff --git a/src/plugins/discover_legacy/public/application/angular/context/query/index.js b/src/plugins/discover_legacy/public/application/angular/context/query/index.js deleted file mode 100644 index cbb0a7484ea7..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query/index.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { QueryActionsProvider } from './actions'; -export { FAILURE_REASONS, LOADING_STATUS } from './constants'; -export { createInitialLoadingStatusState } from './state'; diff --git a/src/plugins/discover_legacy/public/application/angular/context/query/state.js b/src/plugins/discover_legacy/public/application/angular/context/query/state.js deleted file mode 100644 index 7a38ea8ebe3a..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query/state.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { LOADING_STATUS } from './constants'; - -export function createInitialLoadingStatusState() { - return { - anchor: LOADING_STATUS.UNINITIALIZED, - predecessors: LOADING_STATUS.UNINITIALIZED, - successors: LOADING_STATUS.UNINITIALIZED, - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/actions.js b/src/plugins/discover_legacy/public/application/angular/context/query_parameters/actions.js deleted file mode 100644 index f191d7c0d5a2..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/actions.js +++ /dev/null @@ -1,86 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { opensearchFilters } from '../../../../../../data/public'; -import { popularizeField } from '../../../helpers/popularize_field'; - -import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE, QUERY_PARAMETER_KEYS } from './constants'; - -export function getQueryParameterActions(filterManager, indexPatterns) { - const setPredecessorCount = (state) => (predecessorCount) => - (state.queryParameters.predecessorCount = clamp( - MIN_CONTEXT_SIZE, - MAX_CONTEXT_SIZE, - predecessorCount - )); - - const setSuccessorCount = (state) => (successorCount) => - (state.queryParameters.successorCount = clamp( - MIN_CONTEXT_SIZE, - MAX_CONTEXT_SIZE, - successorCount - )); - - const setQueryParameters = (state) => (queryParameters) => - Object.assign(state.queryParameters, _.pick(queryParameters, QUERY_PARAMETER_KEYS)); - - const updateFilters = () => (filters) => { - filterManager.setFilters(filters); - }; - - const addFilter = (state) => async (field, values, operation) => { - const indexPatternId = state.queryParameters.indexPatternId; - const newFilters = opensearchFilters.generateFilters( - filterManager, - field, - values, - operation, - indexPatternId - ); - filterManager.addFilters(newFilters); - if (indexPatterns) { - const indexPattern = await indexPatterns.get(indexPatternId); - await popularizeField(indexPattern, field.name, indexPatterns); - } - }; - - return { - addFilter, - updateFilters, - setPredecessorCount, - setQueryParameters, - setSuccessorCount, - }; -} - -function clamp(minimum, maximum, value) { - return Math.max(Math.min(maximum, value), minimum); -} diff --git a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/actions.test.ts b/src/plugins/discover_legacy/public/application/angular/context/query_parameters/actions.test.ts deleted file mode 100644 index 2e3c69a32ff6..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/actions.test.ts +++ /dev/null @@ -1,168 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -// @ts-ignore -import { getQueryParameterActions } from './actions'; -import { FilterManager } from '../../../../../../data/public'; -import { coreMock } from '../../../../../../../core/public/mocks'; -const setupMock = coreMock.createSetup(); - -let state: { - queryParameters: { - defaultStepSize: number; - indexPatternId: string; - predecessorCount: number; - successorCount: number; - }; -}; -let filterManager: FilterManager; -let filterManagerSpy: jest.SpyInstance; - -beforeEach(() => { - filterManager = new FilterManager(setupMock.uiSettings); - filterManagerSpy = jest.spyOn(filterManager, 'addFilters'); - - state = { - queryParameters: { - defaultStepSize: 3, - indexPatternId: 'INDEX_PATTERN_ID', - predecessorCount: 10, - successorCount: 10, - }, - }; -}); - -describe('context query_parameter actions', function () { - describe('action addFilter', () => { - it('should pass the given arguments to the filterManager', () => { - const { addFilter } = getQueryParameterActions(filterManager); - - addFilter(state)('FIELD_NAME', 'FIELD_VALUE', 'FILTER_OPERATION'); - - // get the generated filter - const generatedFilter = filterManagerSpy.mock.calls[0][0][0]; - const queryKeys = Object.keys(generatedFilter.query.match_phrase); - expect(filterManagerSpy.mock.calls.length).toBe(1); - expect(queryKeys[0]).toBe('FIELD_NAME'); - expect(generatedFilter.query.match_phrase[queryKeys[0]]).toBe('FIELD_VALUE'); - }); - - it('should pass the index pattern id to the filterManager', () => { - const { addFilter } = getQueryParameterActions(filterManager); - addFilter(state)('FIELD_NAME', 'FIELD_VALUE', 'FILTER_OPERATION'); - const generatedFilter = filterManagerSpy.mock.calls[0][0][0]; - expect(generatedFilter.meta.index).toBe('INDEX_PATTERN_ID'); - }); - }); - describe('action setPredecessorCount', () => { - it('should set the predecessorCount to the given value', () => { - const { setPredecessorCount } = getQueryParameterActions(filterManager); - setPredecessorCount(state)(20); - expect(state.queryParameters.predecessorCount).toBe(20); - }); - - it('should limit the predecessorCount to 0 as a lower bound', () => { - const { setPredecessorCount } = getQueryParameterActions(filterManager); - setPredecessorCount(state)(-1); - expect(state.queryParameters.predecessorCount).toBe(0); - }); - - it('should limit the predecessorCount to 10000 as an upper bound', () => { - const { setPredecessorCount } = getQueryParameterActions(filterManager); - setPredecessorCount(state)(20000); - expect(state.queryParameters.predecessorCount).toBe(10000); - }); - }); - describe('action setSuccessorCount', () => { - it('should set the successorCount to the given value', function () { - const { setSuccessorCount } = getQueryParameterActions(filterManager); - setSuccessorCount(state)(20); - - expect(state.queryParameters.successorCount).toBe(20); - }); - - it('should limit the successorCount to 0 as a lower bound', () => { - const { setSuccessorCount } = getQueryParameterActions(filterManager); - setSuccessorCount(state)(-1); - expect(state.queryParameters.successorCount).toBe(0); - }); - - it('should limit the successorCount to 10000 as an upper bound', () => { - const { setSuccessorCount } = getQueryParameterActions(filterManager); - setSuccessorCount(state)(20000); - expect(state.queryParameters.successorCount).toBe(10000); - }); - }); - describe('action setQueryParameters', function () { - const { setQueryParameters } = getQueryParameterActions(filterManager); - - it('should update the queryParameters with valid properties from the given object', function () { - const newState = { - ...state, - queryParameters: { - additionalParameter: 'ADDITIONAL_PARAMETER', - }, - }; - - const actualState = setQueryParameters(newState)({ - anchorId: 'ANCHOR_ID', - columns: ['column'], - defaultStepSize: 3, - filters: ['filter'], - indexPatternId: 'INDEX_PATTERN', - predecessorCount: 100, - successorCount: 100, - sort: ['field'], - }); - - expect(actualState).toEqual({ - additionalParameter: 'ADDITIONAL_PARAMETER', - anchorId: 'ANCHOR_ID', - columns: ['column'], - defaultStepSize: 3, - filters: ['filter'], - indexPatternId: 'INDEX_PATTERN', - predecessorCount: 100, - successorCount: 100, - sort: ['field'], - }); - }); - - it('should ignore invalid properties', function () { - const newState = { ...state }; - - setQueryParameters(newState)({ - additionalParameter: 'ADDITIONAL_PARAMETER', - }); - - expect(state.queryParameters).toEqual(newState.queryParameters); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/constants.ts b/src/plugins/discover_legacy/public/application/angular/context/query_parameters/constants.ts deleted file mode 100644 index a6dcc5653c87..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/constants.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { createInitialQueryParametersState } from './state'; - -export const MAX_CONTEXT_SIZE = 10000; // OpenSearch's default maximum size limit -export const MIN_CONTEXT_SIZE = 0; -export const QUERY_PARAMETER_KEYS = Object.keys(createInitialQueryParametersState()); diff --git a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/index.js b/src/plugins/discover_legacy/public/application/angular/context/query_parameters/index.js deleted file mode 100644 index 03f172bd12cb..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/index.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getQueryParameterActions } from './actions'; -export { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE, QUERY_PARAMETER_KEYS } from './constants'; -export { createInitialQueryParametersState } from './state'; diff --git a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/state.ts b/src/plugins/discover_legacy/public/application/angular/context/query_parameters/state.ts deleted file mode 100644 index a9f44a0f7bef..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context/query_parameters/state.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 function createInitialQueryParametersState( - defaultStepSize: number = 5, - tieBreakerField: string = '_doc' -) { - return { - anchorType: null, - anchorId: null, - columns: [], - defaultStepSize, - filters: [], - indexPatternId: null, - predecessorCount: 0, - successorCount: 0, - sort: [], - tieBreakerField, - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context_app.html b/src/plugins/discover_legacy/public/application/angular/context_app.html deleted file mode 100644 index 1d3971a41132..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context_app.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - -
- - - - - -
-
-
- - -
-
- -
-
- - - -
\ No newline at end of file diff --git a/src/plugins/discover_legacy/public/application/angular/context_app.js b/src/plugins/discover_legacy/public/application/angular/context_app.js deleted file mode 100644 index fa487c726612..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context_app.js +++ /dev/null @@ -1,151 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { CONTEXT_STEP_SETTING, CONTEXT_TIE_BREAKER_FIELDS_SETTING } from '../../../common'; -import { getAngularModule, getServices } from '../../opensearch_dashboards_services'; -import contextAppTemplate from './context_app.html'; -import './context/components/action_bar'; -import { getFirstSortableField } from './context/api/utils/sorting'; -import { - createInitialQueryParametersState, - getQueryParameterActions, - QUERY_PARAMETER_KEYS, -} from './context/query_parameters'; -import { - createInitialLoadingStatusState, - FAILURE_REASONS, - LOADING_STATUS, - QueryActionsProvider, -} from './context/query'; -import { callAfterBindingsWorkaround } from './context/helpers/call_after_bindings_workaround'; - -getAngularModule().directive('contextApp', function ContextApp() { - return { - bindToController: true, - controller: callAfterBindingsWorkaround(ContextAppController), - controllerAs: 'contextApp', - restrict: 'E', - scope: { - anchorId: '=', - columns: '=', - indexPattern: '=', - filters: '=', - predecessorCount: '=', - successorCount: '=', - sort: '=', - }, - template: contextAppTemplate, - }; -}); - -function ContextAppController($scope, Private) { - const { filterManager, indexPatterns, uiSettings } = getServices(); - const queryParameterActions = getQueryParameterActions(filterManager, indexPatterns); - const queryActions = Private(QueryActionsProvider); - this.state = createInitialState( - parseInt(uiSettings.get(CONTEXT_STEP_SETTING), 10), - getFirstSortableField(this.indexPattern, uiSettings.get(CONTEXT_TIE_BREAKER_FIELDS_SETTING)) - ); - - this.actions = _.mapValues( - { - ...queryParameterActions, - ...queryActions, - }, - (action) => (...args) => action(this.state)(...args) - ); - - this.constants = { - FAILURE_REASONS, - LOADING_STATUS, - }; - - $scope.$watchGroup( - [ - () => this.state.rows.predecessors, - () => this.state.rows.anchor, - () => this.state.rows.successors, - ], - (newValues) => this.actions.setAllRows(...newValues) - ); - - /** - * Sync properties to state - */ - $scope.$watchCollection( - () => ({ - ..._.pick(this, QUERY_PARAMETER_KEYS), - indexPatternId: this.indexPattern.id, - }), - (newQueryParameters) => { - const { queryParameters } = this.state; - if ( - newQueryParameters.indexPatternId !== queryParameters.indexPatternId || - newQueryParameters.anchorId !== queryParameters.anchorId || - !_.isEqual(newQueryParameters.sort, queryParameters.sort) - ) { - this.actions.fetchAllRowsWithNewQueryParameters(_.cloneDeep(newQueryParameters)); - } else if ( - newQueryParameters.predecessorCount !== queryParameters.predecessorCount || - newQueryParameters.successorCount !== queryParameters.successorCount || - !_.isEqual(newQueryParameters.filters, queryParameters.filters) - ) { - this.actions.fetchContextRowsWithNewQueryParameters(_.cloneDeep(newQueryParameters)); - } - } - ); - - /** - * Sync state to properties - */ - $scope.$watchCollection( - () => ({ - predecessorCount: this.state.queryParameters.predecessorCount, - successorCount: this.state.queryParameters.successorCount, - }), - (newParameters) => { - _.assign(this, newParameters); - } - ); -} - -function createInitialState(defaultStepSize, tieBreakerField) { - return { - queryParameters: createInitialQueryParametersState(defaultStepSize, tieBreakerField), - rows: { - all: [], - anchor: null, - predecessors: [], - successors: [], - }, - loadingStatus: createInitialLoadingStatusState(), - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/context_state.test.ts b/src/plugins/discover_legacy/public/application/angular/context_state.test.ts deleted file mode 100644 index 23d4581a158b..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context_state.test.ts +++ /dev/null @@ -1,204 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getState } from './context_state'; -import { createBrowserHistory, History } from 'history'; -import { FilterManager, Filter } from '../../../../data/public'; -import { coreMock } from '../../../../../core/public/mocks'; -const setupMock = coreMock.createSetup(); - -describe('Test Discover Context State', () => { - let history: History; - let state: any; - const getCurrentUrl = () => history.createHref(history.location); - beforeEach(async () => { - history = createBrowserHistory(); - history.push('/'); - state = await getState({ - defaultStepSize: '4', - timeFieldName: 'time', - history, - }); - state.startSync(); - }); - afterEach(() => { - state.stopSync(); - }); - test('getState function default return', () => { - expect(state.appState.getState()).toMatchInlineSnapshot(` - Object { - "columns": Array [ - "_source", - ], - "filters": Array [], - "predecessorCount": 4, - "sort": Array [ - "time", - "desc", - ], - "successorCount": 4, - } - `); - expect(state.globalState.getState()).toMatchInlineSnapshot(`null`); - expect(state.startSync).toBeDefined(); - expect(state.stopSync).toBeDefined(); - expect(state.getFilters()).toStrictEqual([]); - }); - test('getState -> setAppState syncing to url', async () => { - state.setAppState({ predecessorCount: 10 }); - state.flushToUrl(); - expect(getCurrentUrl()).toMatchInlineSnapshot( - `"/#?_a=(columns:!(_source),filters:!(),predecessorCount:10,sort:!(time,desc),successorCount:4)"` - ); - }); - test('getState -> url to appState syncing', async () => { - history.push( - '/#?_a=(columns:!(_source),predecessorCount:1,sort:!(time,desc),successorCount:1)' - ); - expect(state.appState.getState()).toMatchInlineSnapshot(` - Object { - "columns": Array [ - "_source", - ], - "predecessorCount": 1, - "sort": Array [ - "time", - "desc", - ], - "successorCount": 1, - } - `); - }); - test('getState -> url to appState syncing with return to a url without state', async () => { - history.push( - '/#?_a=(columns:!(_source),predecessorCount:1,sort:!(time,desc),successorCount:1)' - ); - expect(state.appState.getState()).toMatchInlineSnapshot(` - Object { - "columns": Array [ - "_source", - ], - "predecessorCount": 1, - "sort": Array [ - "time", - "desc", - ], - "successorCount": 1, - } - `); - history.push('/'); - expect(state.appState.getState()).toMatchInlineSnapshot(` - Object { - "columns": Array [ - "_source", - ], - "predecessorCount": 1, - "sort": Array [ - "time", - "desc", - ], - "successorCount": 1, - } - `); - }); - - test('getState -> filters', async () => { - const filterManager = new FilterManager(setupMock.uiSettings); - const filterGlobal = { - query: { match: { extension: { query: 'jpg', type: 'phrase' } } }, - meta: { index: 'logstash-*', negate: false, disabled: false, alias: null }, - } as Filter; - filterManager.setGlobalFilters([filterGlobal]); - const filterApp = { - query: { match: { extension: { query: 'png', type: 'phrase' } } }, - meta: { index: 'logstash-*', negate: true, disabled: false, alias: null }, - } as Filter; - filterManager.setAppFilters([filterApp]); - state.setFilters(filterManager); - expect(state.getFilters()).toMatchInlineSnapshot(` - Array [ - Object { - "$state": Object { - "store": "globalState", - }, - "meta": Object { - "alias": null, - "disabled": false, - "index": "logstash-*", - "key": "extension", - "negate": false, - "params": Object { - "query": "jpg", - }, - "type": "phrase", - "value": [Function], - }, - "query": Object { - "match": Object { - "extension": Object { - "query": "jpg", - "type": "phrase", - }, - }, - }, - }, - Object { - "$state": Object { - "store": "appState", - }, - "meta": Object { - "alias": null, - "disabled": false, - "index": "logstash-*", - "key": "extension", - "negate": true, - "params": Object { - "query": "png", - }, - "type": "phrase", - "value": [Function], - }, - "query": Object { - "match": Object { - "extension": Object { - "query": "png", - "type": "phrase", - }, - }, - }, - }, - ] - `); - state.flushToUrl(); - expect(getCurrentUrl()).toMatchInlineSnapshot( - `"/#?_g=(filters:!(('$state':(store:globalState),meta:(alias:!n,disabled:!f,index:'logstash-*',key:extension,negate:!f,params:(query:jpg),type:phrase),query:(match:(extension:(query:jpg,type:phrase))))))&_a=(columns:!(_source),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'logstash-*',key:extension,negate:!t,params:(query:png),type:phrase),query:(match:(extension:(query:png,type:phrase))))),predecessorCount:4,sort:!(time,desc),successorCount:4)"` - ); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/context_state.ts b/src/plugins/discover_legacy/public/application/angular/context_state.ts deleted file mode 100644 index 1b19b1d43e78..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/context_state.ts +++ /dev/null @@ -1,307 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { History } from 'history'; -import { NotificationsStart } from 'opensearch-dashboards/public'; -import { - createStateContainer, - createOsdUrlStateStorage, - syncStates, - BaseStateContainer, - withNotifyOnErrors, -} from '../../../../opensearch_dashboards_utils/public'; -import { opensearchFilters, FilterManager, Filter, Query } from '../../../../data/public'; - -export interface AppState { - /** - * Columns displayed in the table, cannot be changed by UI, just in discover's main app - */ - columns: string[]; - /** - * Array of filters - */ - filters: Filter[]; - /** - * Number of records to be fetched before anchor records (newer records) - */ - predecessorCount: number; - /** - * Sorting of the records to be fetched, assumed to be a legacy parameter - */ - sort: string[]; - /** - * Number of records to be fetched after the anchor records (older records) - */ - successorCount: number; - query?: Query; -} - -interface GlobalState { - /** - * Array of filters - */ - filters: Filter[]; -} - -interface GetStateParams { - /** - * Number of records to be fetched when 'Load' link/button is clicked - */ - defaultStepSize: string; - /** - * The timefield used for sorting - */ - timeFieldName: string; - /** - * Determins the use of long vs. short/hashed urls - */ - storeInSessionStorage?: boolean; - /** - * History instance to use - */ - history: History; - - /** - * Core's notifications.toasts service - * In case it is passed in, - * osdUrlStateStorage will use it notifying about inner errors - */ - toasts?: NotificationsStart['toasts']; -} - -interface GetStateReturn { - /** - * Global state, the _g part of the URL - */ - globalState: BaseStateContainer; - /** - * App state, the _a part of the URL - */ - appState: BaseStateContainer; - /** - * Start sync between state and URL - */ - startSync: () => void; - /** - * Stop sync between state and URL - */ - stopSync: () => void; - /** - * Set app state to with a partial new app state - */ - setAppState: (newState: Partial) => void; - /** - * Get all filters, global and app state - */ - getFilters: () => Filter[]; - /** - * Set global state and app state filters by the given FilterManager instance - * @param filterManager - */ - setFilters: (filterManager: FilterManager) => void; - /** - * sync state to URL, used for testing - */ - flushToUrl: (replace?: boolean) => void; -} -const GLOBAL_STATE_URL_KEY = '_g'; -const APP_STATE_URL_KEY = '_a'; - -/** - * Builds and returns appState and globalState containers - * provides helper functions to start/stop syncing with URL - */ -export function getState({ - defaultStepSize, - timeFieldName, - storeInSessionStorage = false, - history, - toasts, -}: GetStateParams): GetStateReturn { - const stateStorage = createOsdUrlStateStorage({ - useHash: storeInSessionStorage, - history, - ...(toasts && withNotifyOnErrors(toasts)), - }); - - const globalStateInitial = stateStorage.get(GLOBAL_STATE_URL_KEY) as GlobalState; - const globalStateContainer = createStateContainer(globalStateInitial); - - const appStateFromUrl = stateStorage.get(APP_STATE_URL_KEY) as AppState; - const appStateInitial = createInitialAppState(defaultStepSize, timeFieldName, appStateFromUrl); - const appStateContainer = createStateContainer(appStateInitial); - - const { start, stop } = syncStates([ - { - storageKey: GLOBAL_STATE_URL_KEY, - stateContainer: { - ...globalStateContainer, - ...{ - set: (value: GlobalState | null) => { - if (value) { - globalStateContainer.set(value); - } - }, - }, - }, - stateStorage, - }, - { - storageKey: APP_STATE_URL_KEY, - stateContainer: { - ...appStateContainer, - ...{ - set: (value: AppState | null) => { - if (value) { - appStateContainer.set(value); - } - }, - }, - }, - stateStorage, - }, - ]); - - return { - globalState: globalStateContainer, - appState: appStateContainer, - startSync: start, - stopSync: stop, - setAppState: (newState: Partial) => { - const oldState = appStateContainer.getState(); - const mergedState = { ...oldState, ...newState }; - - if (!isEqualState(oldState, mergedState)) { - appStateContainer.set(mergedState); - } - }, - getFilters: () => [ - ...getFilters(globalStateContainer.getState()), - ...getFilters(appStateContainer.getState()), - ], - setFilters: (filterManager: FilterManager) => { - // global state filters - const globalFilters = filterManager.getGlobalFilters(); - const globalFilterChanged = !isEqualFilters( - globalFilters, - getFilters(globalStateContainer.getState()) - ); - if (globalFilterChanged) { - globalStateContainer.set({ filters: globalFilters }); - } - // app state filters - const appFilters = filterManager.getAppFilters(); - const appFilterChanged = !isEqualFilters( - appFilters, - getFilters(appStateContainer.getState()) - ); - if (appFilterChanged) { - appStateContainer.set({ ...appStateContainer.getState(), ...{ filters: appFilters } }); - } - }, - // helper function just needed for testing - flushToUrl: (replace?: boolean) => stateStorage.flush({ replace }), - }; -} - -/** - * Helper function to compare 2 different filter states - */ -export function isEqualFilters(filtersA: Filter[], filtersB: Filter[]) { - if (!filtersA && !filtersB) { - return true; - } else if (!filtersA || !filtersB) { - return false; - } - return opensearchFilters.compareFilters( - filtersA, - filtersB, - opensearchFilters.COMPARE_ALL_OPTIONS - ); -} - -/** - * Helper function to compare 2 different states, is needed since comparing filters - * works differently, doesn't work with _.isEqual - */ -function isEqualState(stateA: AppState | GlobalState, stateB: AppState | GlobalState) { - if (!stateA && !stateB) { - return true; - } else if (!stateA || !stateB) { - return false; - } - const { filters: stateAFilters = [], ...stateAPartial } = stateA; - const { filters: stateBFilters = [], ...stateBPartial } = stateB; - return ( - _.isEqual(stateAPartial, stateBPartial) && - opensearchFilters.compareFilters( - stateAFilters, - stateBFilters, - opensearchFilters.COMPARE_ALL_OPTIONS - ) - ); -} - -/** - * Helper function to return array of filter object of a given state - */ -function getFilters(state: AppState | GlobalState): Filter[] { - if (!state || !Array.isArray(state.filters)) { - return []; - } - return state.filters; -} - -/** - * Helper function to return the initial app state, which is a merged object of url state and - * default state. The default size is the default number of successor/predecessor records to fetch - */ -function createInitialAppState( - defaultSize: string, - timeFieldName: string, - urlState: AppState -): AppState { - const defaultState = { - columns: ['_source'], - filters: [], - predecessorCount: parseInt(defaultSize, 10), - sort: [timeFieldName, 'desc'], - successorCount: parseInt(defaultSize, 10), - }; - if (typeof urlState !== 'object') { - return defaultState; - } - - return { - ...defaultState, - ...urlState, - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/directives/__snapshots__/no_results.test.js.snap b/src/plugins/discover_legacy/public/application/angular/directives/__snapshots__/no_results.test.js.snap deleted file mode 100644 index f2abb590008c..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/__snapshots__/no_results.test.js.snap +++ /dev/null @@ -1,230 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DiscoverNoResults props queryLanguage supports lucene and renders doc link 1`] = ` -Array [ -
, -
-
-
-
-
-
-
-
-

- Refine your query -

-

- The search bar at the top uses OpenSearch’s support for Lucene - - Query String syntax - - - (opens in a new tab or window) - - - . Here are some examples of how you can search for web server logs that have been parsed into a few fields. -

-
-
-
-
-
- - Find requests that contain the number 200, in any field - -
-
-
- - - 200 - - -
-
-
- - Find 200 in the status field - -
-
-
- - - status:200 - - -
-
-
- - Find all status codes between 400-499 - -
-
-
- - - status:[400 TO 499] - - -
-
-
- - Find status codes 400-499 with the extension php - -
-
-
- - - status:[400 TO 499] AND extension:PHP - - -
-
-
- - Find status codes 400-499 with the extension php or html - -
-
-
- - - status:[400 TO 499] AND (extension:php OR extension:html) - - -
-
-
-
-
, -] -`; - -exports[`DiscoverNoResults props timeFieldName renders time range feedback 1`] = ` -Array [ -
, -
-
-
-
-
-
-
-
-

- Expand your time range -

-

- One or more of the indices you’re looking at contains a date field. Your query may not match anything in the current time range, or there may not be any data at all in the currently selected time range. You can try changing the time range to one which contains data. -

-
-
-
, -] -`; diff --git a/src/plugins/discover_legacy/public/application/angular/directives/_histogram.scss b/src/plugins/discover_legacy/public/application/angular/directives/_histogram.scss deleted file mode 100644 index 1e625fa064e2..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/_histogram.scss +++ /dev/null @@ -1,11 +0,0 @@ -.dscHistogram__header--partial { - font-weight: $euiFontWeightRegular; - min-width: $euiSize * 12; -} - -// Temporary override to inlined styles provided by ElasticCharts theming -// Will be unnecessary when we migrate the histogram to a different rendering library: -// https: //github.com/opensearch-project/OpenSearch-Dashboards/issues/4643 -.dscHistogram .echChartBackground { - background-color: inherit !important; -} diff --git a/src/plugins/discover_legacy/public/application/angular/directives/_index.scss b/src/plugins/discover_legacy/public/application/angular/directives/_index.scss deleted file mode 100644 index 01f5bbb6fd57..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import "no_results"; -@import "histogram"; diff --git a/src/plugins/discover_legacy/public/application/angular/directives/_no_results.scss b/src/plugins/discover_legacy/public/application/angular/directives/_no_results.scss deleted file mode 100644 index 7ea945e820bf..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/_no_results.scss +++ /dev/null @@ -1,3 +0,0 @@ -.dscNoResults { - max-width: 1000px; -} diff --git a/src/plugins/discover_legacy/public/application/angular/directives/debounce/debounce.js b/src/plugins/discover_legacy/public/application/angular/directives/debounce/debounce.js deleted file mode 100644 index da0f4893b909..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/debounce/debounce.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -// Debounce service, angularized version of lodash debounce -// borrowed heavily from https://github.com/shahata/angular-debounce - -export function createDebounceProviderTimeout($timeout) { - return function (func, wait, options) { - let timeout; - let args; - let self; - let result; - options = _.defaults(options || {}, { - leading: false, - trailing: true, - invokeApply: true, - }); - - function debounce() { - self = this; - args = arguments; - - const later = function () { - timeout = null; - if (!options.leading || options.trailing) { - result = func.apply(self, args); - } - }; - - const callNow = options.leading && !timeout; - - if (timeout) { - $timeout.cancel(timeout); - } - timeout = $timeout(later, wait, options.invokeApply); - - if (callNow) { - result = func.apply(self, args); - } - - return result; - } - - debounce.cancel = function () { - $timeout.cancel(timeout); - timeout = null; - }; - - return debounce; - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/directives/debounce/debounce.test.ts b/src/plugins/discover_legacy/public/application/angular/directives/debounce/debounce.test.ts deleted file mode 100644 index 635ed560df40..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/debounce/debounce.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 sinon, { SinonSpy } from 'sinon'; -import angular, { auto, ITimeoutService } from 'angular'; -import 'angular-mocks'; -import 'angular-sanitize'; -import 'angular-route'; - -// @ts-ignore -import { createDebounceProviderTimeout } from './debounce'; -import { coreMock } from '../../../../../../../core/public/mocks'; -import { initializeInnerAngularModule } from '../../../../get_inner_angular'; -import { navigationPluginMock } from '../../../../../../navigation/public/mocks'; -import { dataPluginMock } from '../../../../../../data/public/mocks'; -import { initAngularBootstrap } from '../../../../../../opensearch_dashboards_legacy/public'; - -describe('debounce service', function () { - let debounce: (fn: () => void, timeout: number, options?: any) => any; - let $timeout: ITimeoutService; - let spy: SinonSpy; - - beforeEach(() => { - spy = sinon.spy(); - - initAngularBootstrap(); - - initializeInnerAngularModule( - 'app/discover', - coreMock.createStart(), - navigationPluginMock.createStartContract(), - dataPluginMock.createStartContract() - ); - - angular.mock.module('app/discover'); - - angular.mock.inject(($injector: auto.IInjectorService, _$timeout_: ITimeoutService) => { - $timeout = _$timeout_; - - debounce = createDebounceProviderTimeout($timeout); - }); - }); - - it('should have a cancel method', function () { - const bouncer = debounce(() => {}, 100); - - expect(bouncer).toHaveProperty('cancel'); - }); - - describe('delayed execution', function () { - const sandbox = sinon.createSandbox(); - - beforeEach(() => sandbox.useFakeTimers()); - afterEach(() => sandbox.restore()); - - it('should delay execution', function () { - const bouncer = debounce(spy, 100); - - bouncer(); - sinon.assert.notCalled(spy); - $timeout.flush(); - sinon.assert.calledOnce(spy); - - spy.resetHistory(); - }); - - it('should fire on leading edge', function () { - const bouncer = debounce(spy, 100, { leading: true }); - - bouncer(); - sinon.assert.calledOnce(spy); - $timeout.flush(); - sinon.assert.calledTwice(spy); - - spy.resetHistory(); - }); - - it('should only fire on leading edge', function () { - const bouncer = debounce(spy, 100, { leading: true, trailing: false }); - - bouncer(); - sinon.assert.calledOnce(spy); - $timeout.flush(); - sinon.assert.calledOnce(spy); - - spy.resetHistory(); - }); - - it('should reset delayed execution', function () { - const cancelSpy = sinon.spy($timeout, 'cancel'); - const bouncer = debounce(spy, 100); - - bouncer(); - sandbox.clock.tick(1); - - bouncer(); - sinon.assert.notCalled(spy); - $timeout.flush(); - sinon.assert.calledOnce(spy); - sinon.assert.calledOnce(cancelSpy); - - spy.resetHistory(); - cancelSpy.resetHistory(); - }); - }); - - describe('cancel', function () { - it('should cancel the $timeout', function () { - const cancelSpy = sinon.spy($timeout, 'cancel'); - const bouncer = debounce(spy, 100); - - bouncer(); - bouncer.cancel(); - sinon.assert.calledOnce(cancelSpy); - // throws if pending timeouts - $timeout.verifyNoPendingTasks(); - - cancelSpy.resetHistory(); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/directives/debounce/index.js b/src/plugins/discover_legacy/public/application/angular/directives/debounce/index.js deleted file mode 100644 index 6acd0d680d4d..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/debounce/index.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { createDebounceProviderTimeout } from './debounce'; diff --git a/src/plugins/discover_legacy/public/application/angular/directives/fixed_scroll.js b/src/plugins/discover_legacy/public/application/angular/directives/fixed_scroll.js deleted file mode 100644 index 6b80caaa1f71..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/fixed_scroll.js +++ /dev/null @@ -1,166 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 $ from 'jquery'; -import _ from 'lodash'; -import { createDebounceProviderTimeout } from './debounce'; - -const SCROLLER_HEIGHT = 20; - -/** - * This directive adds a fixed horizontal scrollbar to the bottom of the window that proxies its scroll events - * to the target element's real scrollbar. This is useful when the target element's horizontal scrollbar - * might be waaaay down the page, like the doc table on Discover. - */ -export function FixedScrollProvider($timeout) { - return { - restrict: 'A', - link: function ($scope, $el) { - return createFixedScroll($scope, $timeout)($el); - }, - }; -} - -export function createFixedScroll($scope, $timeout) { - const debounce = createDebounceProviderTimeout($timeout); - return function (el) { - const $el = typeof el.css === 'function' ? el : $(el); - let $window = $(window); - let $scroller = $('
').height(SCROLLER_HEIGHT); - - /** - * Remove the listeners bound in listen() - * @type {function} - */ - let unlisten = _.noop; - - /** - * Listen for scroll events on the $scroller and the $el, sets unlisten() - * - * unlisten must be called before calling or listen() will throw an Error - * - * Since the browser emits "scroll" events after setting scrollLeft - * the listeners also prevent tug-of-war - * - * @throws {Error} If unlisten was not called first - * @return {undefined} - */ - function listen() { - if (unlisten !== _.noop) { - throw new Error('fixedScroll listeners were not cleaned up properly before re-listening!'); - } - - let blockTo; - function bind($from, $to) { - function handler() { - if (blockTo === $to) return (blockTo = null); - $to.scrollLeft((blockTo = $from).scrollLeft()); - } - - $from.on('scroll', handler); - return function () { - $from.off('scroll', handler); - }; - } - - unlisten = _.flow(bind($el, $scroller), bind($scroller, $el), function () { - unlisten = _.noop; - }); - } - - /** - * Revert DOM changes and event listeners - * @return {undefined} - */ - function cleanUp() { - unlisten(); - $scroller.detach(); - $el.css('padding-bottom', 0); - } - - /** - * Modify the DOM and attach event listeners based on need. - * Is called many times to re-setup, must be idempotent - * @return {undefined} - */ - function setup() { - cleanUp(); - - const containerWidth = $el.width(); - const contentWidth = $el.prop('scrollWidth'); - const containerHorizOverflow = contentWidth - containerWidth; - - const elTop = $el.offset().top - $window.scrollTop(); - const elBottom = elTop + $el.height(); - const windowVertOverflow = elBottom - $window.height(); - - const requireScroller = containerHorizOverflow > 0 && windowVertOverflow > 0; - if (!requireScroller) return; - - // push the content away from the scroller - $el.css('padding-bottom', SCROLLER_HEIGHT); - - // fill the scroller with a dummy element that mimics the content - $scroller - .width(containerWidth) - .html($('
').css({ width: contentWidth, height: SCROLLER_HEIGHT })) - .insertAfter($el); - - // listen for scroll events - listen(); - } - - let width; - let scrollWidth; - function checkWidth() { - const newScrollWidth = $el.prop('scrollWidth'); - const newWidth = $el.width(); - - if (scrollWidth !== newScrollWidth || width !== newWidth) { - $scope.$apply(setup); - - scrollWidth = newScrollWidth; - width = newWidth; - } - } - - const debouncedCheckWidth = debounce(checkWidth, 100, { - invokeApply: false, - }); - $scope.$watch(debouncedCheckWidth); - - function destroy() { - cleanUp(); - debouncedCheckWidth.cancel(); - $scroller = $window = null; - } - return destroy; - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/directives/fixed_scroll.test.js b/src/plugins/discover_legacy/public/application/angular/directives/fixed_scroll.test.js deleted file mode 100644 index cf0e6d9f331c..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/fixed_scroll.test.js +++ /dev/null @@ -1,274 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 angular from 'angular'; -import 'angular-mocks'; -import $ from 'jquery'; - -import sinon from 'sinon'; - -import { initAngularBootstrap } from '../../../../../opensearch_dashboards_legacy/public'; -import { FixedScrollProvider } from './fixed_scroll'; - -const testModuleName = 'fixedScroll'; - -angular.module(testModuleName, []).directive('fixedScroll', FixedScrollProvider); - -describe('FixedScroll directive', function () { - const sandbox = sinon.createSandbox(); - let mockWidth; - let mockHeight; - let currentWidth = 120; - let currentHeight = 120; - let currentJqLiteWidth = 120; - let spyScrollWidth; - - let compile; - let flushPendingTasks; - const trash = []; - - beforeAll(() => { - mockWidth = jest.spyOn($.prototype, 'width').mockImplementation(function (width) { - if (width === undefined) { - return currentWidth; - } else { - currentWidth = width; - return this; - } - }); - mockHeight = jest.spyOn($.prototype, 'height').mockImplementation(function (height) { - if (height === undefined) { - return currentHeight; - } else { - currentHeight = height; - return this; - } - }); - angular.element.prototype.width = jest.fn(function (width) { - if (width === undefined) { - return currentJqLiteWidth; - } else { - currentJqLiteWidth = width; - return this; - } - }); - angular.element.prototype.offset = jest.fn(() => ({ top: 0 })); - }); - - beforeEach(() => { - currentJqLiteWidth = 120; - initAngularBootstrap(); - - angular.mock.module(testModuleName); - angular.mock.inject(($compile, $rootScope, $timeout) => { - flushPendingTasks = function flushPendingTasks() { - $rootScope.$digest(); - $timeout.flush(); - }; - - compile = function (ratioY, ratioX) { - if (ratioX == null) ratioX = ratioY; - - // since the directive works at the sibling level we create a - // parent for everything to happen in - const $parent = $('
').css({ - position: 'fixed', - top: 0, - left: 0, - right: 0, - bottom: 0, - }); - - $parent.appendTo(document.body); - trash.push($parent); - - const $el = $('
') - .css({ - 'overflow-x': 'auto', - width: $parent.width(), - }) - .appendTo($parent); - - spyScrollWidth = jest.spyOn(window.HTMLElement.prototype, 'scrollWidth', 'get'); - spyScrollWidth.mockReturnValue($parent.width() * ratioX); - angular.element.prototype.height = jest.fn(() => $parent.height() * ratioY); - - const $content = $('
') - .css({ - width: $parent.width() * ratioX, - height: $parent.height() * ratioY, - }) - .appendTo($el); - - $compile($parent)($rootScope); - flushPendingTasks(); - - return { - $container: $el, - $content: $content, - $scroller: $parent.find('.dscTableFixedScroll__scroller'), - }; - }; - }); - }); - - afterEach(function () { - trash.splice(0).forEach(function ($el) { - $el.remove(); - }); - - sandbox.restore(); - spyScrollWidth.mockRestore(); - }); - - afterAll(() => { - mockWidth.mockRestore(); - mockHeight.mockRestore(); - delete angular.element.prototype.width; - delete angular.element.prototype.height; - delete angular.element.prototype.offset; - }); - - test('does nothing when not needed', function () { - let els = compile(0.5, 1.5); - expect(els.$scroller).toHaveLength(0); - - els = compile(1.5, 0.5); - expect(els.$scroller).toHaveLength(0); - }); - - test('attaches a scroller below the element when the content is larger then the container', function () { - const els = compile(1.5); - expect(els.$scroller.length).toBe(1); - }); - - test('copies the width of the container', function () { - const els = compile(1.5); - expect(els.$scroller.width()).toBe(els.$container.width()); - }); - - test('mimics the scrollWidth of the element', function () { - const els = compile(1.5); - expect(els.$scroller.prop('scrollWidth')).toBe(els.$container.prop('scrollWidth')); - }); - - describe('scroll event handling / tug of war prevention', function () { - test('listens when needed, unlistens when not needed', function (done) { - const on = sandbox.spy($.fn, 'on'); - const off = sandbox.spy($.fn, 'off'); - const jqLiteOn = sandbox.spy(angular.element.prototype, 'on'); - const jqLiteOff = sandbox.spy(angular.element.prototype, 'off'); - - const els = compile(1.5); - expect(on.callCount).toBe(1); - expect(jqLiteOn.callCount).toBe(1); - checkThisVals('$.fn.on', on, jqLiteOn); - - expect(off.callCount).toBe(0); - expect(jqLiteOff.callCount).toBe(0); - currentJqLiteWidth = els.$container.prop('scrollWidth'); - flushPendingTasks(); - expect(off.callCount).toBe(1); - expect(jqLiteOff.callCount).toBe(1); - checkThisVals('$.fn.off', off, jqLiteOff); - done(); - - function checkThisVals(namejQueryFn, spyjQueryFn, spyjqLiteFn) { - // the this values should be different - expect(spyjQueryFn.thisValues[0].is(spyjqLiteFn.thisValues[0])).toBeFalsy(); - // but they should be either $scroller or $container - const el = spyjQueryFn.thisValues[0]; - - if (el.is(els.$scroller) || el.is(els.$container)) return; - - done.fail('expected ' + namejQueryFn + ' to be called with $scroller or $container'); - } - }); - - // Turn off this row because tests failed. - // Scroll event is not catched in fixed_scroll. - // As container is jquery element in test but inside fixed_scroll it's a jqLite element. - // it would need jquery in jest to make this work. - [ - //{ from: '$container', to: '$scroller' }, - { from: '$scroller', to: '$container' }, - ].forEach(function (names) { - describe('scroll events ' + JSON.stringify(names), function () { - let spyJQueryScrollLeft; - let spyJQLiteScrollLeft; - let els; - let $from; - let $to; - - beforeEach(function () { - spyJQueryScrollLeft = sandbox.spy($.fn, 'scrollLeft'); - spyJQLiteScrollLeft = sandbox.stub(); - angular.element.prototype.scrollLeft = spyJQLiteScrollLeft; - els = compile(1.5); - $from = els[names.from]; - $to = els[names.to]; - }); - - test('transfers the scrollLeft', function () { - expect(spyJQueryScrollLeft.callCount).toBe(0); - expect(spyJQLiteScrollLeft.callCount).toBe(0); - $from.scroll(); - expect(spyJQueryScrollLeft.callCount).toBe(1); - expect(spyJQLiteScrollLeft.callCount).toBe(1); - - // first call should read the scrollLeft from the $container - const firstCall = spyJQueryScrollLeft.getCall(0); - expect(firstCall.args).toEqual([]); - - // second call should be setting the scrollLeft on the $scroller - const secondCall = spyJQLiteScrollLeft.getCall(0); - expect(secondCall.args).toEqual([firstCall.returnValue]); - }); - - /** - * In practice, calling $el.scrollLeft() causes the "scroll" event to trigger, - * but the browser seems to be very careful about triggering the event too much - * and I can't reliably recreate the browsers behavior in a test. So... faking it! - */ - test('prevents tug of war by ignoring echo scroll events', function () { - $from.scroll(); - expect(spyJQueryScrollLeft.callCount).toBe(1); - expect(spyJQLiteScrollLeft.callCount).toBe(1); - - spyJQueryScrollLeft.resetHistory(); - spyJQLiteScrollLeft.resetHistory(); - $to.scroll(); - expect(spyJQueryScrollLeft.callCount).toBe(0); - expect(spyJQLiteScrollLeft.callCount).toBe(0); - }); - }); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/directives/histogram.tsx b/src/plugins/discover_legacy/public/application/angular/directives/histogram.tsx deleted file mode 100644 index 4c1263192322..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/histogram.tsx +++ /dev/null @@ -1,362 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui'; -import moment from 'moment-timezone'; -import { unitOfTime } from 'moment'; -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { euiThemeVars } from '@osd/ui-shared-deps/theme'; - -import { - AnnotationDomainType, - Axis, - Chart, - HistogramBarSeries, - LineAnnotation, - Position, - ScaleType, - Settings, - RectAnnotation, - TooltipValue, - TooltipType, - ElementClickListener, - XYChartElementEvent, - BrushEndListener, - Theme, -} from '@elastic/charts'; - -import { i18n } from '@osd/i18n'; -import { IUiSettingsClient } from 'opensearch-dashboards/public'; -import { EuiChartThemeType } from '@elastic/eui/dist/eui_charts_theme'; -import { Subscription, combineLatest } from 'rxjs'; -import { getServices } from '../../../opensearch_dashboards_services'; -import { Chart as IChart } from '../helpers/point_series'; - -export interface DiscoverHistogramProps { - chartData: IChart; - timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; -} - -interface DiscoverHistogramState { - chartsTheme: EuiChartThemeType['theme']; - chartsBaseTheme: Theme; -} - -function findIntervalFromDuration( - dateValue: number, - opensearchValue: number, - opensearchUnit: unitOfTime.Base, - timeZone: string -) { - const date = moment.tz(dateValue, timeZone); - const startOfDate = moment.tz(date, timeZone).startOf(opensearchUnit); - const endOfDate = moment - .tz(date, timeZone) - .startOf(opensearchUnit) - .add(opensearchValue, opensearchUnit); - return endOfDate.valueOf() - startOfDate.valueOf(); -} - -function getIntervalInMs( - value: number, - opensearchValue: number, - opensearchUnit: unitOfTime.Base, - timeZone: string -): number { - switch (opensearchUnit) { - case 's': - return 1000 * opensearchValue; - case 'ms': - return 1 * opensearchValue; - default: - return findIntervalFromDuration(value, opensearchValue, opensearchUnit, timeZone); - } -} - -function getTimezone(uiSettings: IUiSettingsClient) { - if (uiSettings.isDefault('dateFormat:tz')) { - const detectedTimezone = moment.tz.guess(); - if (detectedTimezone) return detectedTimezone; - else return moment().format('Z'); - } else { - return uiSettings.get('dateFormat:tz', 'Browser'); - } -} - -export function findMinInterval( - xValues: number[], - opensearchValue: number, - opensearchUnit: string, - timeZone: string -): number { - return xValues.reduce((minInterval, currentXvalue, index) => { - let currentDiff = minInterval; - if (index > 0) { - currentDiff = Math.abs(xValues[index - 1] - currentXvalue); - } - const singleUnitInterval = getIntervalInMs( - currentXvalue, - opensearchValue, - opensearchUnit as unitOfTime.Base, - timeZone - ); - return Math.min(minInterval, singleUnitInterval, currentDiff); - }, Number.MAX_SAFE_INTEGER); -} - -export class DiscoverHistogram extends Component { - public static propTypes = { - chartData: PropTypes.object, - timefilterUpdateHandler: PropTypes.func, - }; - - private subscription?: Subscription; - public state = { - chartsTheme: getServices().theme.chartsDefaultTheme, - chartsBaseTheme: getServices().theme.chartsDefaultBaseTheme, - }; - - componentDidMount() { - this.subscription = combineLatest( - getServices().theme.chartsTheme$, - getServices().theme.chartsBaseTheme$ - ).subscribe(([chartsTheme, chartsBaseTheme]) => - this.setState({ chartsTheme, chartsBaseTheme }) - ); - } - - componentWillUnmount() { - if (this.subscription) { - this.subscription.unsubscribe(); - } - } - - public onBrushEnd: BrushEndListener = ({ x }) => { - if (!x) { - return; - } - const [from, to] = x; - this.props.timefilterUpdateHandler({ from, to }); - }; - - public onElementClick = (xInterval: number): ElementClickListener => ([elementData]) => { - const startRange = (elementData as XYChartElementEvent)[0].x; - - const range = { - from: startRange, - to: startRange + xInterval, - }; - - this.props.timefilterUpdateHandler(range); - }; - - public formatXValue = (val: string) => { - const xAxisFormat = this.props.chartData.xAxisFormat.params!.pattern; - - return moment(val).format(xAxisFormat); - }; - - public renderBarTooltip = (xInterval: number, domainStart: number, domainEnd: number) => ( - headerData: TooltipValue - ): JSX.Element | string => { - const headerDataValue = headerData.value; - const formattedValue = this.formatXValue(headerDataValue); - - const partialDataText = i18n.translate('discover.histogram.partialData.bucketTooltipText', { - defaultMessage: - 'The selected time range does not include this entire bucket, it may contain partial data.', - }); - - if (headerDataValue < domainStart || headerDataValue + xInterval > domainEnd) { - return ( - - - - - - {partialDataText} - - -

{formattedValue}

-
- ); - } - - return formattedValue; - }; - - public render() { - const uiSettings = getServices().uiSettings; - const timeZone = getTimezone(uiSettings); - const { chartData } = this.props; - const { chartsTheme, chartsBaseTheme } = this.state; - - if (!chartData) { - return null; - } - - const data = chartData.values; - - /** - * Deprecation: [interval] on [date_histogram] is deprecated, use [fixed_interval] or [calendar_interval]. - * see https://github.com/elastic/kibana/issues/27410 - * TODO: Once the Discover query has been update, we should change the below to use the new field - */ - const { intervalOpenSearchValue, intervalOpenSearchUnit, interval } = chartData.ordered; - const xInterval = interval.asMilliseconds(); - - const xValues = chartData.xAxisOrderedValues; - const lastXValue = xValues[xValues.length - 1]; - - const domain = chartData.ordered; - const domainStart = domain.min.valueOf(); - const domainEnd = domain.max.valueOf(); - - const domainMin = data[0]?.x > domainStart ? domainStart : data[0]?.x; - const domainMax = domainEnd - xInterval > lastXValue ? domainEnd - xInterval : lastXValue; - - const xDomain = { - min: domainMin, - max: domainMax, - minInterval: findMinInterval( - xValues, - intervalOpenSearchValue, - intervalOpenSearchUnit, - timeZone - ), - }; - - // Domain end of 'now' will be milliseconds behind current time, so we extend time by 1 minute and check if - // the annotation is within this range; if so, the line annotation uses the domainEnd as its value - const now = moment(); - const isAnnotationAtEdge = moment(domainEnd).add(60000).isAfter(now) && now.isAfter(domainEnd); - const lineAnnotationValue = isAnnotationAtEdge ? domainEnd : now; - - const lineAnnotationData = [ - { - dataValue: lineAnnotationValue, - }, - ]; - const isDarkMode = uiSettings.get('theme:darkMode'); - - const lineAnnotationStyle = { - line: { - strokeWidth: 2, - stroke: euiThemeVars.euiColorDanger, - opacity: 0.7, - }, - }; - - const rectAnnotations = []; - if (domainStart !== domainMin) { - rectAnnotations.push({ - coordinates: { - x1: domainStart, - }, - }); - } - if (domainEnd !== domainMax) { - rectAnnotations.push({ - coordinates: { - x0: domainEnd, - }, - }); - } - - const rectAnnotationStyle = { - stroke: isDarkMode ? euiThemeVars.euiColorLightShade : euiThemeVars.euiColorDarkShade, - strokeWidth: 0, - opacity: isDarkMode ? 0.6 : 0.2, - fill: isDarkMode ? euiThemeVars.euiColorLightShade : euiThemeVars.euiColorDarkShade, - }; - - const tooltipProps = { - headerFormatter: this.renderBarTooltip(xInterval, domainStart, domainEnd), - type: TooltipType.VerticalCursor, - }; - - return ( - - - - - - - - - ); - } -} diff --git a/src/plugins/discover_legacy/public/application/angular/directives/index.js b/src/plugins/discover_legacy/public/application/angular/directives/index.js deleted file mode 100644 index d81152164c42..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/index.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { DiscoverNoResults } from './no_results'; -import { DiscoverUninitialized } from './uninitialized'; -import { DiscoverHistogram } from './histogram'; -import { getAngularModule } from '../../../opensearch_dashboards_services'; - -const app = getAngularModule(); - -app.directive('discoverNoResults', (reactDirective) => reactDirective(DiscoverNoResults)); - -app.directive('discoverUninitialized', (reactDirective) => reactDirective(DiscoverUninitialized)); - -app.directive('discoverHistogram', (reactDirective) => reactDirective(DiscoverHistogram)); diff --git a/src/plugins/discover_legacy/public/application/angular/directives/no_results.js b/src/plugins/discover_legacy/public/application/angular/directives/no_results.js deleted file mode 100644 index 1495296e9dbb..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/no_results.js +++ /dev/null @@ -1,225 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { Component, Fragment } from 'react'; -import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; -import PropTypes from 'prop-types'; - -import { - EuiCallOut, - EuiCode, - EuiDescriptionList, - EuiFlexGroup, - EuiFlexItem, - EuiLink, - EuiSpacer, - EuiText, -} from '@elastic/eui'; -import { getServices } from '../../../opensearch_dashboards_services'; - -// eslint-disable-next-line react/prefer-stateless-function -export class DiscoverNoResults extends Component { - static propTypes = { - timeFieldName: PropTypes.string, - queryLanguage: PropTypes.string, - }; - - render() { - const { timeFieldName, queryLanguage } = this.props; - - let timeFieldMessage; - - if (timeFieldName) { - timeFieldMessage = ( - - - - -

- -

- -

- -

-
-
- ); - } - - let luceneQueryMessage; - - if (queryLanguage === 'lucene') { - const searchExamples = [ - { - description: 200, - title: ( - - - - - - ), - }, - { - description: status:200, - title: ( - - - - - - ), - }, - { - description: status:[400 TO 499], - title: ( - - - - - - ), - }, - { - description: status:[400 TO 499] AND extension:PHP, - title: ( - - - - - - ), - }, - { - description: status:[400 TO 499] AND (extension:php OR extension:html), - title: ( - - - - - - ), - }, - ]; - - luceneQueryMessage = ( - - - - -

- -

- -

- - - - ), - }} - /> -

-
- - - - - - -
- ); - } - - return ( - - - - - - - - } - color="warning" - iconType="help" - data-test-subj="discoverNoResults" - /> - {timeFieldMessage} - {luceneQueryMessage} - - - - - ); - } -} diff --git a/src/plugins/discover_legacy/public/application/angular/directives/no_results.test.js b/src/plugins/discover_legacy/public/application/angular/directives/no_results.test.js deleted file mode 100644 index e6b1c6b73eb3..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/no_results.test.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { renderWithIntl } from 'test_utils/enzyme_helpers'; - -import { DiscoverNoResults } from './no_results'; - -jest.mock('../../../opensearch_dashboards_services', () => { - return { - getServices: () => ({ - docLinks: { - links: { - opensearch: { - queryDSL: { - base: 'documentation-link', - }, - }, - }, - }, - }), - }; -}); - -beforeEach(() => { - jest.clearAllMocks(); -}); - -describe('DiscoverNoResults', () => { - describe('props', () => { - describe('timeFieldName', () => { - test('renders time range feedback', () => { - const component = renderWithIntl(); - - expect(component).toMatchSnapshot(); - }); - }); - - describe('queryLanguage', () => { - test('supports lucene and renders doc link', () => { - const component = renderWithIntl( - 'documentation-link'} /> - ); - - expect(component).toMatchSnapshot(); - }); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/directives/render_complete.ts b/src/plugins/discover_legacy/public/application/angular/directives/render_complete.ts deleted file mode 100644 index 4409910a8e5c..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/render_complete.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { IScope } from 'angular'; -import { RenderCompleteListener } from '../../../../../opensearch_dashboards_utils/public'; - -export function createRenderCompleteDirective() { - return { - controller($scope: IScope, $element: JQLite) { - const el = $element[0]; - const renderCompleteListener = new RenderCompleteListener(el); - $scope.$on('$destroy', renderCompleteListener.destroy); - }, - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/directives/uninitialized.tsx b/src/plugins/discover_legacy/public/application/angular/directives/uninitialized.tsx deleted file mode 100644 index 9cc47b034d1e..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/directives/uninitialized.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { FormattedMessage, I18nProvider } from '@osd/i18n/react'; - -import { EuiButton, EuiEmptyPrompt, EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui'; - -interface Props { - onRefresh: () => void; -} - -export const DiscoverUninitialized = ({ onRefresh }: Props) => { - return ( - - - - - - - - } - body={ -

- -

- } - actions={ - - - - } - /> -
-
-
-
- ); -}; diff --git a/src/plugins/discover_legacy/public/application/angular/discover.js b/src/plugins/discover_legacy/public/application/angular/discover.js deleted file mode 100644 index f8a96928784c..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/discover.js +++ /dev/null @@ -1,1156 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import React from 'react'; -import { Subscription, Subject, merge } from 'rxjs'; -import { debounceTime } from 'rxjs/operators'; -import moment from 'moment'; -import dateMath from '@elastic/datemath'; -import { i18n } from '@osd/i18n'; -import { getState, splitState } from './discover_state'; - -import { RequestAdapter } from '../../../../inspector/public'; -import { - opensearchFilters, - indexPatterns as indexPatternsUtils, - connectToQueryState, - syncQueryStateWithUrl, -} from '../../../../data/public'; -import { SavedObjectSaveModal, showSaveModal } from '../../../../saved_objects/public'; -import { getSortArray, getSortForSearchSource } from './doc_table'; -import { createFixedScroll } from './directives/fixed_scroll'; -import * as columnActions from './doc_table/actions/columns'; -import indexTemplateLegacy from './discover_legacy.html'; -import { showOpenSearchPanel } from '../components/top_nav/show_open_search_panel'; -import { addHelpMenuToAppChrome } from '../components/help_menu/help_menu_util'; -import { discoverResponseHandler } from './response_handler'; -import { - getRequestInspectorStats, - getResponseInspectorStats, - getServices, - getHeaderActionMenuMounter, - getUrlTracker, - unhashUrl, - subscribeWithScope, - tabifyAggResponse, - getAngularModule, - redirectWhenMissing, -} from '../../opensearch_dashboards_services'; - -const { - core, - chrome, - data, - history: getHistory, - indexPatterns, - filterManager, - share, - timefilter, - toastNotifications, - uiSettings: config, - visualizations, -} = getServices(); - -import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../helpers/breadcrumbs'; -import { validateTimeRange } from '../helpers/validate_time_range'; -import { popularizeField } from '../helpers/popularize_field'; -import { getSwitchIndexPatternAppState } from '../helpers/get_switch_index_pattern_app_state'; -import { getIndexPatternId } from '../helpers/get_index_pattern_id'; -import { addFatalError } from '../../../../opensearch_dashboards_legacy/public'; -import { - DEFAULT_COLUMNS_SETTING, - SAMPLE_SIZE_SETTING, - SORT_DEFAULT_ORDER_SETTING, - SEARCH_ON_PAGE_LOAD_SETTING, - DOC_HIDE_TIME_COLUMN_SETTING, - MODIFY_COLUMNS_ON_SWITCH, -} from '../../../common'; -import { NEW_DISCOVER_APP } from '../../../../discover/public'; - -const fetchStatuses = { - UNINITIALIZED: 'uninitialized', - LOADING: 'loading', - COMPLETE: 'complete', -}; - -const app = getAngularModule(); - -app.config(($routeProvider) => { - const defaults = { - requireDefaultIndex: true, - requireUICapability: 'discover.show', - k7Breadcrumbs: ($route, $injector) => - $injector.invoke($route.current.params.id ? getSavedSearchBreadcrumbs : getRootBreadcrumbs), - badge: (uiCapabilities) => { - if (uiCapabilities.discover.save) { - return undefined; - } - - return { - text: i18n.translate('discover.badge.readOnly.text', { - defaultMessage: 'Read only', - }), - tooltip: i18n.translate('discover.badge.readOnly.tooltip', { - defaultMessage: 'Unable to save searches', - }), - iconType: 'glasses', - }; - }, - }; - const discoverRoute = { - ...defaults, - template: indexTemplateLegacy, - reloadOnSearch: false, - resolve: { - savedObjects: function ($route, Promise) { - const history = getHistory(); - const savedSearchId = $route.current.params.id; - return data.indexPatterns.ensureDefaultIndexPattern(history).then(() => { - const { appStateContainer } = getState({ history }); - const { index } = appStateContainer.getState(); - return Promise.props({ - ip: indexPatterns.getCache().then((indexPatternList) => { - /** - * In making the indexPattern modifiable it was placed in appState. Unfortunately, - * the load order of AppState conflicts with the load order of many other things - * so in order to get the name of the index we should use, and to switch to the - * default if necessary, we parse the appState with a temporary State object and - * then destroy it immediatly after we're done - * - * @type {State} - */ - const id = getIndexPatternId(index, indexPatternList, config.get('defaultIndex')); - return Promise.props({ - list: indexPatternList, - loaded: indexPatterns.get(id), - stateVal: index, - stateValFound: !!index && id === index, - }); - }), - savedSearch: getServices() - .getSavedSearchById(savedSearchId) - .then((savedSearch) => { - if (savedSearchId) { - chrome.recentlyAccessed.add( - savedSearch.getFullPath(), - savedSearch.title, - savedSearchId - ); - } - return savedSearch; - }) - .catch( - redirectWhenMissing({ - history, - navigateToApp: core.application.navigateToApp, - mapping: { - search: '/', - 'index-pattern': { - app: 'management', - path: `opensearch-dashboards/objects/savedSearches/${$route.current.params.id}`, - }, - }, - toastNotifications, - onBeforeRedirect() { - getUrlTracker().setTrackedUrl('/'); - }, - }) - ), - }); - }); - }, - }, - }; - - $routeProvider.when('/view/:id?', discoverRoute); - $routeProvider.when('/', discoverRoute); -}); - -app.directive('discoverApp', function () { - return { - restrict: 'E', - controllerAs: 'discoverApp', - controller: discoverController, - }; -}); - -function discoverController($element, $route, $scope, $timeout, $window, Promise, uiCapabilities) { - const { isDefault: isDefaultType } = indexPatternsUtils; - const subscriptions = new Subscription(); - const refetch$ = new Subject(); - let inspectorRequest; - const savedSearch = $route.current.locals.savedObjects.savedSearch; - $scope.searchSource = savedSearch.searchSource; - $scope.indexPattern = resolveIndexPatternLoading(); - //used for functional testing - $scope.fetchCounter = 0; - - const getTimeField = () => { - return isDefaultType($scope.indexPattern) ? $scope.indexPattern.timeFieldName : undefined; - }; - - const history = getHistory(); - - const { - appStateContainer, - startSync: startStateSync, - stopSync: stopStateSync, - setAppState, - replaceUrlAppState, - isAppStateDirty, - osdUrlStateStorage, - getPreviousAppState, - resetInitialAppState, - } = getState({ - defaultAppState: getStateDefaults(), - storeInSessionStorage: config.get('state:storeInSessionStorage'), - history, - toasts: core.notifications.toasts, - }); - if (appStateContainer.getState().index !== $scope.indexPattern.id) { - //used index pattern is different than the given by url/state which is invalid - setAppState({ index: $scope.indexPattern.id }); - } - $scope.state = { ...appStateContainer.getState() }; - - // syncs `_g` portion of url with query services - const { stop: stopSyncingGlobalStateWithUrl } = syncQueryStateWithUrl( - data.query, - osdUrlStateStorage - ); - - // sync initial app filters from state to filterManager - filterManager.setAppFilters(_.cloneDeep(appStateContainer.getState().filters)); - data.query.queryString.setQuery(appStateContainer.getState().query); - - const stopSyncingQueryAppStateWithStateContainer = connectToQueryState( - data.query, - appStateContainer, - { - filters: opensearchFilters.FilterStateStore.APP_STATE, - query: true, - } - ); - - const appStateUnsubscribe = appStateContainer.subscribe(async (newState) => { - const { state: newStatePartial } = splitState(newState); - const { state: oldStatePartial } = splitState(getPreviousAppState()); - - if (!_.isEqual(newStatePartial, oldStatePartial)) { - $scope.$evalAsync(async () => { - if (oldStatePartial.index !== newStatePartial.index) { - //in case of index switch the route has currently to be reloaded, legacy - return; - } - - $scope.state = { ...newState }; - - // detect changes that should trigger fetching of new data - const changes = ['interval', 'sort'].filter( - (prop) => !_.isEqual(newStatePartial[prop], oldStatePartial[prop]) - ); - - if (changes.length) { - refetch$.next(); - } - }); - } - }); - - // this listener is waiting for such a path http://localhost:5601/app/discover#/ - // which could be set through pressing "New" button in top nav or go to "Discover" plugin from the sidebar - // to reload the page in a right way - const unlistenHistoryBasePath = history.listen(({ pathname, search, hash }) => { - if (!search && !hash && pathname === '/') { - $route.reload(); - } - }); - - $scope.setIndexPattern = async (id) => { - const nextIndexPattern = await indexPatterns.get(id); - if (nextIndexPattern) { - const nextAppState = getSwitchIndexPatternAppState( - $scope.indexPattern, - nextIndexPattern, - $scope.state.columns, - $scope.state.sort, - config.get(MODIFY_COLUMNS_ON_SWITCH) - ); - await replaceUrlAppState(nextAppState); - $route.reload(); - } - }; - - // update data source when filters update - subscriptions.add( - subscribeWithScope( - $scope, - filterManager.getUpdates$(), - { - next: () => { - $scope.state.filters = filterManager.getAppFilters(); - $scope.updateDataSource(); - }, - }, - (error) => addFatalError(core.fatalErrors, error) - ) - ); - - const inspectorAdapters = { - requests: new RequestAdapter(), - }; - - $scope.timefilterUpdateHandler = (ranges) => { - timefilter.setTime({ - from: moment(ranges.from).toISOString(), - to: moment(ranges.to).toISOString(), - mode: 'absolute', - }); - }; - $scope.minimumVisibleRows = 50; - $scope.fetchStatus = fetchStatuses.UNINITIALIZED; - $scope.showSaveQuery = uiCapabilities.discover.saveQuery; - - let abortController; - $scope.$on('$destroy', () => { - if (abortController) abortController.abort(); - savedSearch.destroy(); - subscriptions.unsubscribe(); - appStateUnsubscribe(); - stopStateSync(); - stopSyncingGlobalStateWithUrl(); - stopSyncingQueryAppStateWithStateContainer(); - unlistenHistoryBasePath(); - }); - - const getTopNavLinks = () => { - const newSearch = { - id: 'new', - label: i18n.translate('discover.localMenu.localMenu.newSearchTitle', { - defaultMessage: 'New', - }), - description: i18n.translate('discover.localMenu.newSearchDescription', { - defaultMessage: 'New Search', - }), - run: function () { - $scope.$evalAsync(() => { - history.push('/'); - }); - }, - testId: 'discoverNewButton', - }; - - const saveSearch = { - id: 'save', - label: i18n.translate('discover.localMenu.saveTitle', { - defaultMessage: 'Save', - }), - description: i18n.translate('discover.localMenu.saveSearchDescription', { - defaultMessage: 'Save Search', - }), - testId: 'discoverSaveButton', - run: async () => { - const onSave = ({ - newTitle, - newCopyOnSave, - isTitleDuplicateConfirmed, - onTitleDuplicate, - }) => { - const currentTitle = savedSearch.title; - savedSearch.title = newTitle; - savedSearch.copyOnSave = newCopyOnSave; - const saveOptions = { - confirmOverwrite: false, - isTitleDuplicateConfirmed, - onTitleDuplicate, - }; - return saveDataSource(saveOptions).then((response) => { - // If the save wasn't successful, put the original values back. - if (!response.id || response.error) { - savedSearch.title = currentTitle; - } else { - resetInitialAppState(); - } - return response; - }); - }; - - const saveModal = ( - {}} - title={savedSearch.title} - showCopyOnSave={!!savedSearch.id} - objectType="search" - description={i18n.translate('discover.localMenu.saveSaveSearchDescription', { - defaultMessage: - 'Save your Discover search so you can use it in visualizations and dashboards', - })} - showDescription={false} - /> - ); - showSaveModal(saveModal, core.i18n.Context); - }, - }; - - const openSearch = { - id: 'open', - label: i18n.translate('discover.localMenu.openTitle', { - defaultMessage: 'Open', - }), - description: i18n.translate('discover.localMenu.openSavedSearchDescription', { - defaultMessage: 'Open Saved Search', - }), - testId: 'discoverOpenButton', - run: () => { - showOpenSearchPanel({ - makeUrl: (searchId) => `#/view/${encodeURIComponent(searchId)}`, - I18nContext: core.i18n.Context, - }); - }, - }; - - const shareSearch = { - id: 'share', - label: i18n.translate('discover.localMenu.shareTitle', { - defaultMessage: 'Share', - }), - description: i18n.translate('discover.localMenu.shareSearchDescription', { - defaultMessage: 'Share Search', - }), - testId: 'shareTopNavButton', - run: async (anchorElement) => { - const sharingData = await this.getSharingData(); - share.toggleShareContextMenu({ - anchorElement, - allowEmbed: false, - allowShortUrl: uiCapabilities.discover.createShortUrl, - shareableUrl: unhashUrl(window.location.href), - objectId: savedSearch.id, - objectType: 'search', - sharingData: { - ...sharingData, - title: savedSearch.title, - }, - isDirty: !savedSearch.id || isAppStateDirty(), - }); - }, - }; - - const inspectSearch = { - id: 'inspect', - label: i18n.translate('discover.localMenu.inspectTitle', { - defaultMessage: 'Inspect', - }), - description: i18n.translate('discover.localMenu.openInspectorForSearchDescription', { - defaultMessage: 'Open Inspector for search', - }), - testId: 'openInspectorButton', - run() { - getServices().inspector.open(inspectorAdapters, { - title: savedSearch.title, - }); - }, - }; - - const newDiscover = { - id: 'discover-new', - label: i18n.translate('discover.localMenu.newDiscoverTitle', { - defaultMessage: 'New Discover', - }), - description: i18n.translate('discover.localMenu.newDiscoverDescription', { - defaultMessage: 'New Discover Experience', - }), - testId: 'discoverNewButton', - run: async function () { - await getServices().uiSettings.set(NEW_DISCOVER_APP, true); - window.location.reload(); - }, - type: 'toggle', - }; - - return [ - newDiscover, - newSearch, - ...(uiCapabilities.discover.save ? [saveSearch] : []), - openSearch, - shareSearch, - inspectSearch, - ]; - }; - $scope.topNavMenu = getTopNavLinks(); - - $scope.searchSource - .setField('index', $scope.indexPattern) - .setField('highlightAll', true) - .setField('version', true); - - // Even when searching rollups, we want to use the default strategy so that we get back a - // document-like response. - $scope.searchSource.setPreferredSearchStrategyId('default'); - - // searchSource which applies time range - const timeRangeSearchSource = savedSearch.searchSource.create(); - - if (isDefaultType($scope.indexPattern)) { - timeRangeSearchSource.setField('filter', () => { - return timefilter.createFilter($scope.indexPattern); - }); - } - - $scope.searchSource.setParent(timeRangeSearchSource); - - const pageTitleSuffix = savedSearch.id && savedSearch.title ? `: ${savedSearch.title}` : ''; - chrome.docTitle.change(`Discover${pageTitleSuffix}`); - const discoverBreadcrumbsTitle = i18n.translate('discover.discoverBreadcrumbTitle', { - defaultMessage: 'Discover', - }); - - if (savedSearch.id && savedSearch.title) { - chrome.setBreadcrumbs([ - { - text: discoverBreadcrumbsTitle, - href: '#/', - }, - { text: savedSearch.title }, - ]); - } else { - chrome.setBreadcrumbs([ - { - text: discoverBreadcrumbsTitle, - }, - ]); - } - - const getFieldCounts = async () => { - // the field counts aren't set until we have the data back, - // so we wait for the fetch to be done before proceeding - if ($scope.fetchStatus === fetchStatuses.COMPLETE) { - return $scope.fieldCounts; - } - - return await new Promise((resolve) => { - const unwatch = $scope.$watch('fetchStatus', (newValue) => { - if (newValue === fetchStatuses.COMPLETE) { - unwatch(); - resolve($scope.fieldCounts); - } - }); - }); - }; - - const getSharingDataFields = async (selectedFields, timeFieldName, hideTimeColumn) => { - if (selectedFields.length === 1 && selectedFields[0] === '_source') { - const fieldCounts = await getFieldCounts(); - return { - searchFields: null, - selectFields: _.keys(fieldCounts).sort(), - }; - } - - const fields = - timeFieldName && !hideTimeColumn ? [timeFieldName, ...selectedFields] : selectedFields; - return { - searchFields: fields, - selectFields: fields, - }; - }; - - this.getSharingData = async () => { - const searchSource = $scope.searchSource.createCopy(); - - const { searchFields, selectFields } = await getSharingDataFields( - $scope.state.columns, - $scope.indexPattern.timeFieldName, - config.get(DOC_HIDE_TIME_COLUMN_SETTING) - ); - searchSource.setField('fields', searchFields); - searchSource.setField( - 'sort', - getSortForSearchSource( - $scope.state.sort, - $scope.indexPattern, - config.get(SORT_DEFAULT_ORDER_SETTING) - ) - ); - searchSource.setField('highlight', null); - searchSource.setField('highlightAll', null); - searchSource.setField('aggs', null); - searchSource.setField('size', null); - - const body = await searchSource.getSearchRequestBody(); - return { - searchRequest: { - index: searchSource.getField('index').title, - body, - }, - fields: selectFields, - metaFields: $scope.indexPattern.metaFields, - conflictedTypesFields: $scope.indexPattern.fields - .filter((f) => f.type === 'conflict') - .map((f) => f.name), - indexPatternId: searchSource.getField('index').id, - }; - }; - - function getStateDefaults() { - const query = $scope.searchSource.getField('query') || data.query.queryString.getDefaultQuery(); - return { - query, - sort: getSortArray(savedSearch.sort, $scope.indexPattern), - columns: - savedSearch.columns.length > 0 - ? savedSearch.columns - : config.get(DEFAULT_COLUMNS_SETTING).slice(), - index: $scope.indexPattern.id, - interval: 'auto', - filters: _.cloneDeep($scope.searchSource.getOwnField('filter')), - }; - } - - $scope.state.index = $scope.indexPattern.id; - $scope.state.sort = getSortArray($scope.state.sort, $scope.indexPattern); - - $scope.opts = { - // number of records to fetch, then paginate through - sampleSize: config.get(SAMPLE_SIZE_SETTING), - timefield: getTimeField(), - savedSearch: savedSearch, - indexPatternList: $route.current.locals.savedObjects.ip.list, - config: config, - fixedScroll: createFixedScroll($scope, $timeout), - setHeaderActionMenu: getHeaderActionMenuMounter(), - }; - - const shouldSearchOnPageLoad = () => { - // A saved search is created on every page load, so we check the ID to see if we're loading a - // previously saved search or if it is just transient - return ( - config.get(SEARCH_ON_PAGE_LOAD_SETTING) || - savedSearch.id !== undefined || - timefilter.getRefreshInterval().pause === false - ); - }; - - const init = _.once(() => { - $scope.updateDataSource().then(async () => { - const fetch$ = merge( - refetch$, - filterManager.getFetches$(), - timefilter.getFetch$(), - timefilter.getAutoRefreshFetch$(), - data.query.queryString.getUpdates$() - ).pipe(debounceTime(100)); - - subscriptions.add( - subscribeWithScope( - $scope, - fetch$, - { - next: $scope.fetch, - }, - (error) => addFatalError(core.fatalErrors, error) - ) - ); - subscriptions.add( - subscribeWithScope( - $scope, - timefilter.getTimeUpdate$(), - { - next: () => { - $scope.updateTime(); - }, - }, - (error) => addFatalError(core.fatalErrors, error) - ) - ); - - $scope.changeInterval = (interval) => { - if (interval) { - setAppState({ interval }); - } - }; - - $scope.$watchMulti( - ['rows', 'fetchStatus'], - (function updateResultState() { - let prev = {}; - const status = { - UNINITIALIZED: 'uninitialized', - LOADING: 'loading', // initial data load - READY: 'ready', // results came back - NO_RESULTS: 'none', // no results came back - }; - - function pick(rows, oldRows, fetchStatus) { - // initial state, pretend we're already loading if we're about to execute a search so - // that the uninitilized message doesn't flash on screen - if (rows == null && oldRows == null && shouldSearchOnPageLoad()) { - return status.LOADING; - } - - if (fetchStatus === fetchStatuses.UNINITIALIZED) { - return status.UNINITIALIZED; - } - - const rowsEmpty = _.isEmpty(rows); - if (rowsEmpty && fetchStatus === fetchStatuses.LOADING) return status.LOADING; - else if (!rowsEmpty) return status.READY; - else return status.NO_RESULTS; - } - - return function () { - const current = { - rows: $scope.rows, - fetchStatus: $scope.fetchStatus, - }; - - $scope.resultState = pick( - current.rows, - prev.rows, - current.fetchStatus, - prev.fetchStatus - ); - - prev = current; - }; - })() - ); - - if (getTimeField()) { - setupVisualization(); - $scope.updateTime(); - } - - init.complete = true; - if (shouldSearchOnPageLoad()) { - refetch$.next(); - } - }); - }); - - async function saveDataSource(saveOptions) { - await $scope.updateDataSource(); - - savedSearch.columns = $scope.state.columns; - savedSearch.sort = $scope.state.sort; - - try { - const id = await savedSearch.save(saveOptions); - $scope.$evalAsync(() => { - if (id) { - toastNotifications.addSuccess({ - title: i18n.translate('discover.notifications.savedSearchTitle', { - defaultMessage: `Search '{savedSearchTitle}' was saved`, - values: { - savedSearchTitle: savedSearch.title, - }, - }), - 'data-test-subj': 'saveSearchSuccess', - }); - - if (savedSearch.id !== $route.current.params.id) { - history.push(`/view/${encodeURIComponent(savedSearch.id)}`); - } else { - // Update defaults so that "reload saved query" functions correctly - setAppState(getStateDefaults()); - chrome.docTitle.change(savedSearch.lastSavedTitle); - chrome.setBreadcrumbs([ - { - text: discoverBreadcrumbsTitle, - href: '#/', - }, - { text: savedSearch.title }, - ]); - } - } - }); - return { id }; - } catch (saveError) { - toastNotifications.addDanger({ - title: i18n.translate('discover.notifications.notSavedSearchTitle', { - defaultMessage: `Search '{savedSearchTitle}' was not saved.`, - values: { - savedSearchTitle: savedSearch.title, - }, - }), - text: saveError.message, - }); - return { error: saveError }; - } - } - - $scope.opts.fetch = $scope.fetch = function () { - // ignore requests to fetch before the app inits - if (!init.complete) return; - $scope.fetchCounter++; - $scope.fetchError = undefined; - $scope.minimumVisibleRows = 50; - if (!validateTimeRange(timefilter.getTime(), toastNotifications)) { - $scope.resultState = 'none'; - return; - } - - // Abort any in-progress requests before fetching again - if (abortController) abortController.abort(); - abortController = new AbortController(); - - $scope - .updateDataSource() - .then(setupVisualization) - .then(function () { - $scope.fetchStatus = fetchStatuses.LOADING; - logInspectorRequest(); - return $scope.searchSource.fetch({ - abortSignal: abortController.signal, - }); - }) - .then(onResults) - .catch((error) => { - // If the request was aborted then no need to surface this error in the UI - if (error instanceof Error && error.name === 'AbortError') return; - - $scope.fetchStatus = fetchStatuses.NO_RESULTS; - $scope.rows = []; - - data.search.showError(error); - }); - }; - - $scope.handleRefresh = function (_payload, isUpdate) { - if (isUpdate === false) { - refetch$.next(); - } - }; - - $scope.updateSavedQueryId = (newSavedQueryId) => { - if (newSavedQueryId) { - setAppState({ savedQuery: newSavedQueryId }); - } else { - // remove savedQueryId from state - const state = { - ...appStateContainer.getState(), - }; - delete state.savedQuery; - appStateContainer.set(state); - } - }; - - function getDimensions(aggs, timeRange) { - const [metric, agg] = aggs; - agg.params.timeRange = timeRange; - const bounds = agg.params.timeRange ? timefilter.calculateBounds(agg.params.timeRange) : null; - agg.buckets.setBounds(bounds); - - const { opensearchUnit, opensearchValue } = agg.buckets.getInterval(); - return { - x: { - accessor: 0, - label: agg.makeLabel(), - format: agg.toSerializedFieldFormat(), - params: { - date: true, - interval: moment.duration(opensearchValue, opensearchUnit), - intervalOpenSearchValue: opensearchValue, - intervalOpenSearchUnit: opensearchUnit, - format: agg.buckets.getScaledDateFormat(), - bounds: agg.buckets.getBounds(), - }, - }, - y: { - accessor: 1, - format: metric.toSerializedFieldFormat(), - label: metric.makeLabel(), - }, - }; - } - - function onResults(resp) { - inspectorRequest.stats(getResponseInspectorStats(resp, $scope.searchSource)).ok({ json: resp }); - - if (getTimeField()) { - const tabifiedData = tabifyAggResponse($scope.vis.data.aggs, resp); - $scope.searchSource.rawResponse = resp; - $scope.histogramData = discoverResponseHandler( - tabifiedData, - getDimensions($scope.vis.data.aggs.aggs, $scope.timeRange) - ); - $scope.updateTime(); - } - - $scope.hits = resp.hits.total; - $scope.rows = resp.hits.hits; - - // if we haven't counted yet, reset the counts - const counts = ($scope.fieldCounts = $scope.fieldCounts || {}); - - $scope.rows.forEach((hit) => { - const fields = Object.keys($scope.indexPattern.flattenHit(hit)); - fields.forEach((fieldName) => { - counts[fieldName] = (counts[fieldName] || 0) + 1; - }); - }); - - $scope.fetchStatus = fetchStatuses.COMPLETE; - } - - function logInspectorRequest() { - inspectorAdapters.requests.reset(); - const title = i18n.translate('discover.inspectorRequestDataTitle', { - defaultMessage: 'data', - }); - const description = i18n.translate('discover.inspectorRequestDescription', { - defaultMessage: 'This request queries OpenSearch to fetch the data for the search.', - }); - inspectorRequest = inspectorAdapters.requests.start(title, { description }); - inspectorRequest.stats(getRequestInspectorStats($scope.searchSource)); - $scope.searchSource.getSearchRequestBody().then((body) => { - inspectorRequest.json(body); - }); - } - - $scope.updateTime = function () { - const { from, to } = timefilter.getTime(); - // this is the timerange for the histogram, should be refactored - $scope.timeRange = { - from: dateMath.parse(from), - to: dateMath.parse(to, { roundUp: true }), - }; - }; - - $scope.toMoment = function (datetime) { - if (!datetime) { - return; - } - return moment(datetime).format(config.get('dateFormat')); - }; - - $scope.resetQuery = function () { - history.push( - $route.current.params.id ? `/view/${encodeURIComponent($route.current.params.id)}` : '/' - ); - $route.reload(); - }; - - $scope.onSkipBottomButtonClick = function () { - // show all the Rows - $scope.minimumVisibleRows = $scope.hits; - - // delay scrolling to after the rows have been rendered - const bottomMarker = $element.find('#discoverBottomMarker'); - $timeout(() => { - bottomMarker.focus(); - // The anchor tag is not technically empty (it's a hack to make Safari scroll) - // so the browser will show a highlight: remove the focus once scrolled - $timeout(() => { - bottomMarker.blur(); - }, 0); - }, 0); - }; - - $scope.newQuery = function () { - history.push('/'); - }; - - $scope.updateDataSource = () => { - const { indexPattern, searchSource } = $scope; - searchSource - .setField('index', $scope.indexPattern) - .setField('size', $scope.opts.sampleSize) - .setField( - 'sort', - getSortForSearchSource( - $scope.state.sort, - indexPattern, - config.get(SORT_DEFAULT_ORDER_SETTING) - ) - ) - .setField('query', data.query.queryString.getQuery() || null) - .setField('filter', filterManager.getFilters()); - return Promise.resolve(); - }; - - $scope.setSortOrder = function setSortOrder(sort) { - setAppState({ sort }); - }; - - // TODO: On array fields, negating does not negate the combination, rather all terms - $scope.filterQuery = function (field, values, operation) { - const { indexPattern } = $scope; - - popularizeField(indexPattern, field.name, indexPatterns); - const newFilters = opensearchFilters.generateFilters( - filterManager, - field, - values, - operation, - $scope.indexPattern.id - ); - return filterManager.addFilters(newFilters); - }; - - $scope.addColumn = function addColumn(columnName) { - if (uiCapabilities.discover.save) { - const { indexPattern } = $scope; - popularizeField(indexPattern, columnName, indexPatterns); - } - const columns = columnActions.addColumn($scope.state.columns, columnName); - setAppState({ columns }); - }; - - $scope.removeColumn = function removeColumn(columnName) { - if (uiCapabilities.discover.save) { - const { indexPattern } = $scope; - popularizeField(indexPattern, columnName, indexPatterns); - } - const columns = columnActions.removeColumn($scope.state.columns, columnName); - // The state's sort property is an array of [sortByColumn,sortDirection] - const sort = $scope.state.sort.length - ? $scope.state.sort.filter((subArr) => subArr[0] !== columnName) - : []; - setAppState({ columns, sort }); - }; - - $scope.moveColumn = function moveColumn(columnName, newIndex) { - const columns = columnActions.moveColumn($scope.state.columns, columnName, newIndex); - setAppState({ columns }); - }; - - $scope.scrollToTop = function () { - $window.scrollTo(0, 0); - }; - - async function setupVisualization() { - // If no timefield has been specified we don't create a histogram of messages - if (!getTimeField()) return; - const { interval: histogramInterval } = $scope.state; - - const visStateAggs = [ - { - type: 'count', - schema: 'metric', - }, - { - type: 'date_histogram', - schema: 'segment', - params: { - field: getTimeField(), - interval: histogramInterval, - timeRange: timefilter.getTime(), - }, - }, - ]; - - $scope.vis = await visualizations.createVis('histogram', { - title: savedSearch.title, - params: { - addLegend: false, - addTimeMarker: true, - }, - data: { - aggs: visStateAggs, - searchSource: $scope.searchSource.getSerializedFields(), - }, - }); - - $scope.searchSource.onRequestStart((searchSource, options) => { - if (!$scope.vis) return; - return $scope.vis.data.aggs.onSearchRequestStart(searchSource, options); - }); - - $scope.searchSource.setField('aggs', function () { - if (!$scope.vis) return; - return $scope.vis.data.aggs.toDsl(); - }); - } - - function getIndexPatternWarning(index) { - return i18n.translate('discover.valueIsNotConfiguredIndexPatternIDWarningTitle', { - defaultMessage: '{stateVal} is not a configured index pattern ID', - values: { - stateVal: `"${index}"`, - }, - }); - } - - function resolveIndexPatternLoading() { - const { - loaded: loadedIndexPattern, - stateVal, - stateValFound, - } = $route.current.locals.savedObjects.ip; - - const ownIndexPattern = $scope.searchSource.getOwnField('index'); - - if (ownIndexPattern && !stateVal) { - return ownIndexPattern; - } - - if (stateVal && !stateValFound) { - const warningTitle = getIndexPatternWarning(); - - if (ownIndexPattern) { - toastNotifications.addWarning({ - title: warningTitle, - text: i18n.translate('discover.showingSavedIndexPatternWarningDescription', { - defaultMessage: - 'Showing the saved index pattern: "{ownIndexPatternTitle}" ({ownIndexPatternId})', - values: { - ownIndexPatternTitle: ownIndexPattern.title, - ownIndexPatternId: ownIndexPattern.id, - }, - }), - }); - return ownIndexPattern; - } - - toastNotifications.addWarning({ - title: warningTitle, - text: i18n.translate('discover.showingDefaultIndexPatternWarningDescription', { - defaultMessage: - 'Showing the default index pattern: "{loadedIndexPatternTitle}" ({loadedIndexPatternId})', - values: { - loadedIndexPatternTitle: loadedIndexPattern.title, - loadedIndexPatternId: loadedIndexPattern.id, - }, - }), - }); - } - - return loadedIndexPattern; - } - - addHelpMenuToAppChrome(chrome); - - init(); - // Propagate current app state to url, then start syncing - replaceUrlAppState().then(() => startStateSync()); -} diff --git a/src/plugins/discover_legacy/public/application/angular/discover_legacy.html b/src/plugins/discover_legacy/public/application/angular/discover_legacy.html deleted file mode 100644 index 8582f71c0cb8..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/discover_legacy.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - diff --git a/src/plugins/discover_legacy/public/application/angular/discover_state.test.ts b/src/plugins/discover_legacy/public/application/angular/discover_state.test.ts deleted file mode 100644 index 96225d4a2a53..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/discover_state.test.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getState, GetStateReturn } from './discover_state'; -import { createBrowserHistory, History } from 'history'; - -let history: History; -let state: GetStateReturn; -const getCurrentUrl = () => history.createHref(history.location); - -describe('Test discover state', () => { - beforeEach(async () => { - history = createBrowserHistory(); - history.push('/'); - state = getState({ - defaultAppState: { index: 'test' }, - history, - }); - await state.replaceUrlAppState({}); - await state.startSync(); - }); - afterEach(() => { - state.stopSync(); - }); - test('setting app state and syncing to URL', async () => { - state.setAppState({ index: 'modified' }); - state.flushToUrl(); - expect(getCurrentUrl()).toMatchInlineSnapshot(`"/#?_a=(index:modified)"`); - }); - - test('changing URL to be propagated to appState', async () => { - history.push('/#?_a=(index:modified)'); - expect(state.appStateContainer.getState()).toMatchInlineSnapshot(` - Object { - "index": "modified", - } - `); - }); - test('URL navigation to url without _a, state should not change', async () => { - history.push('/#?_a=(index:modified)'); - history.push('/'); - expect(state.appStateContainer.getState()).toMatchInlineSnapshot(` - Object { - "index": "modified", - } - `); - }); - - test('isAppStateDirty returns whether the current state has changed', async () => { - state.setAppState({ index: 'modified' }); - expect(state.isAppStateDirty()).toBeTruthy(); - state.resetInitialAppState(); - expect(state.isAppStateDirty()).toBeFalsy(); - }); - - test('getPreviousAppState returns the state before the current', async () => { - state.setAppState({ index: 'first' }); - const stateA = state.appStateContainer.getState(); - state.setAppState({ index: 'second' }); - expect(state.getPreviousAppState()).toEqual(stateA); - }); -}); - -describe('Test discover state with legacy migration', () => { - test('migration of legacy query ', async () => { - history = createBrowserHistory(); - history.push( - "/#?_a=(query:(query_string:(analyze_wildcard:!t,query:'type:nice%20name:%22yeah%22')))" - ); - state = getState({ - defaultAppState: { index: 'test' }, - history, - }); - expect(state.appStateContainer.getState()).toMatchInlineSnapshot(` - Object { - "index": "test", - "query": Object { - "language": "lucene", - "query": Object { - "query_string": Object { - "analyze_wildcard": true, - "query": "type:nice name:\\"yeah\\"", - }, - }, - }, - } - `); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/discover_state.ts b/src/plugins/discover_legacy/public/application/angular/discover_state.ts deleted file mode 100644 index 0570b64d24d9..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/discover_state.ts +++ /dev/null @@ -1,256 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { isEqual } from 'lodash'; -import { History } from 'history'; -import { NotificationsStart } from 'opensearch-dashboards/public'; -import { - createStateContainer, - createOsdUrlStateStorage, - syncState, - ReduxLikeStateContainer, - IOsdUrlStateStorage, - withNotifyOnErrors, -} from '../../../../opensearch_dashboards_utils/public'; -import { opensearchFilters, Filter, Query } from '../../../../data/public'; -import { migrateLegacyQuery } from '../helpers/migrate_legacy_query'; - -export interface AppState { - /** - * Columns displayed in the table - */ - columns?: string[]; - /** - * Array of applied filters - */ - filters?: Filter[]; - /** - * id of the used index pattern - */ - index?: string; - /** - * Used interval of the histogram - */ - interval?: string; - /** - * Lucence or DQL query - */ - query?: Query; - /** - * Array of the used sorting [[field,direction],...] - */ - sort?: string[][]; - /** - * id of the used saved query - */ - savedQuery?: string; -} - -interface GetStateParams { - /** - * Default state used for merging with with URL state to get the initial state - */ - defaultAppState?: AppState; - /** - * Determins the use of long vs. short/hashed urls - */ - storeInSessionStorage?: boolean; - /** - * Browser history - */ - history: History; - - /** - * Core's notifications.toasts service - * In case it is passed in, - * osdUrlStateStorage will use it notifying about inner errors - */ - toasts?: NotificationsStart['toasts']; -} - -export interface GetStateReturn { - /** - * osdUrlStateStorage - */ - osdUrlStateStorage: IOsdUrlStateStorage; - /** - * App state, the _a part of the URL - */ - appStateContainer: ReduxLikeStateContainer; - /** - * Start sync between state and URL - */ - startSync: () => void; - /** - * Stop sync between state and URL - */ - stopSync: () => void; - /** - * Set app state to with a partial new app state - */ - setAppState: (newState: Partial) => void; - /** - * Set state in Url using history.replace - */ - replaceUrlAppState: (newState: Partial) => Promise; - /** - * Sync state to URL, used for testing - */ - flushToUrl: () => void; - /** - * Reset initial state to the current app state - */ - resetInitialAppState: () => void; - /** - * Return the Appstate before the current app state, useful for diffing changes - */ - getPreviousAppState: () => AppState; - /** - * Returns whether the current app state is different to the initial state - */ - isAppStateDirty: () => void; -} -const APP_STATE_URL_KEY = '_a'; - -/** - * Builds and returns appState and globalState containers and helper functions - * Used to sync URL with UI state - */ -export function getState({ - defaultAppState = {}, - storeInSessionStorage = false, - history, - toasts, -}: GetStateParams): GetStateReturn { - const stateStorage = createOsdUrlStateStorage({ - useHash: storeInSessionStorage, - history, - ...(toasts && withNotifyOnErrors(toasts)), - }); - - const appStateFromUrl = stateStorage.get(APP_STATE_URL_KEY) as AppState; - - if (appStateFromUrl && appStateFromUrl.query && !appStateFromUrl.query.language) { - appStateFromUrl.query = migrateLegacyQuery(appStateFromUrl.query); - } - - let initialAppState = { - ...defaultAppState, - ...appStateFromUrl, - }; - let previousAppState: AppState; - const appStateContainer = createStateContainer(initialAppState); - - const appStateContainerModified = { - ...appStateContainer, - set: (value: AppState | null) => { - if (value) { - previousAppState = appStateContainer.getState(); - appStateContainer.set(value); - } - }, - }; - - const { start, stop } = syncState({ - storageKey: APP_STATE_URL_KEY, - stateContainer: appStateContainerModified, - stateStorage, - }); - - return { - osdUrlStateStorage: stateStorage, - appStateContainer: appStateContainerModified, - startSync: start, - stopSync: stop, - setAppState: (newPartial: AppState) => setState(appStateContainerModified, newPartial), - replaceUrlAppState: async (newPartial: AppState = {}) => { - const state = { ...appStateContainer.getState(), ...newPartial }; - await stateStorage.set(APP_STATE_URL_KEY, state, { replace: true }); - }, - resetInitialAppState: () => { - initialAppState = appStateContainer.getState(); - }, - getPreviousAppState: () => previousAppState, - flushToUrl: () => stateStorage.flush(), - isAppStateDirty: () => !isEqualState(initialAppState, appStateContainer.getState()), - }; -} - -/** - * Helper function to merge a given new state with the existing state and to set the given state - * container - */ -export function setState(stateContainer: ReduxLikeStateContainer, newState: AppState) { - const oldState = stateContainer.getState(); - const mergedState = { ...oldState, ...newState }; - if (!isEqualState(oldState, mergedState)) { - stateContainer.set(mergedState); - } -} - -/** - * Helper function to compare 2 different filter states - */ -export function isEqualFilters(filtersA: Filter[], filtersB: Filter[]) { - if (!filtersA && !filtersB) { - return true; - } else if (!filtersA || !filtersB) { - return false; - } - return opensearchFilters.compareFilters( - filtersA, - filtersB, - opensearchFilters.COMPARE_ALL_OPTIONS - ); -} - -/** - * helper function to extract filters of the given state - * returns a state object without filters and an array of filters - */ -export function splitState(state: AppState = {}) { - const { filters = [], ...statePartial } = state; - return { filters, state: statePartial }; -} - -/** - * Helper function to compare 2 different state, is needed since comparing filters - * works differently - */ -export function isEqualState(stateA: AppState, stateB: AppState) { - if (!stateA && !stateB) { - return true; - } else if (!stateA || !stateB) { - return false; - } - const { filters: stateAFilters = [], ...stateAPartial } = stateA; - const { filters: stateBFilters = [], ...stateBPartial } = stateB; - return isEqual(stateAPartial, stateBPartial) && isEqualFilters(stateAFilters, stateBFilters); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc.html b/src/plugins/discover_legacy/public/application/angular/doc.html deleted file mode 100644 index dcd5760eff15..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc.html +++ /dev/null @@ -1,8 +0,0 @@ -
- -
diff --git a/src/plugins/discover_legacy/public/application/angular/doc.ts b/src/plugins/discover_legacy/public/application/angular/doc.ts deleted file mode 100644 index 584815be9342..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getAngularModule, getServices } from '../../opensearch_dashboards_services'; -// @ts-ignore -import { getRootBreadcrumbs } from '../helpers/breadcrumbs'; -import html from './doc.html'; -import { Doc } from '../components/doc/doc'; - -interface LazyScope extends ng.IScope { - [key: string]: any; -} - -const { timefilter } = getServices(); -const app = getAngularModule(); -app.directive('discoverDoc', function (reactDirective: any) { - return reactDirective( - Doc, - [ - ['id', { watchDepth: 'value' }], - ['index', { watchDepth: 'value' }], - ['indexPatternId', { watchDepth: 'reference' }], - ['indexPatternService', { watchDepth: 'reference' }], - ], - { restrict: 'E' } - ); -}); - -app.config(($routeProvider: any) => { - $routeProvider - .when('/doc/:indexPattern/:index/:type', { - redirectTo: '/doc/:indexPattern/:index', - }) - // the new route, opensearch 7 deprecated types, opensearch 8 removed them - .when('/doc/:indexPattern/:index', { - // have to be written as function expression, because it's not compiled in dev mode - // eslint-disable-next-line object-shorthand - controller: function ($scope: LazyScope, $route: any) { - timefilter.disableAutoRefreshSelector(); - timefilter.disableTimeRangeSelector(); - $scope.id = $route.current.params.id; - $scope.index = $route.current.params.index; - $scope.indexPatternId = $route.current.params.indexPattern; - $scope.indexPatternService = getServices().indexPatterns; - }, - template: html, - k7Breadcrumbs: ($route: any) => [ - ...getRootBreadcrumbs(), - { - text: `${$route.current.params.index}#${$route.current.params.id}`, - }, - ], - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/_doc_table.scss b/src/plugins/discover_legacy/public/application/angular/doc_table/_doc_table.scss deleted file mode 100644 index bc75d4171004..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/_doc_table.scss +++ /dev/null @@ -1,158 +0,0 @@ -/** - * 1. Stack content vertically so the table can scroll when its constrained by a fixed container height. - */ -doc-table { - @include euiScrollBar; - - overflow: auto; - flex: 1 1 100%; - flex-direction: column; /* 1 */ - - th { - text-align: left; - font-weight: bold; - } - - .spinner { - position: absolute; - top: 40%; - left: 0; - right: 0; - z-index: $euiZLevel1; - opacity: 0.5; - } -} - -.osdDocTable__container.loading { - opacity: 0.5; -} - -.osdDocTable { - font-size: $euiFontSizeXS; - - th { - white-space: nowrap; - padding-right: $euiSizeS; - - .fa { - font-size: 1.1em; - } - } -} - -.osd-table, -.osdDocTable { - /** - * Style OpenSearch document _source in table view
key:
value
- * Use alpha so this will stand out against non-white backgrounds, e.g. the highlighted - * row in the Context Log. - */ - - dl.source { - margin-bottom: 0; - line-height: 2em; - word-break: break-word; - - dt, - dd { - display: inline; - } - - dt { - background-color: tintOrShade($euiColorPrimary, 90%, 70%); - color: $euiTextColor; - padding: ($euiSizeXS / 2) $euiSizeXS; - margin-right: $euiSizeXS; - word-break: normal; - border-radius: $euiBorderRadius; - } - } -} - -.osdDocTable__row { - td { - position: relative; - - &:hover { - .osdDocTableRowFilterButton { - opacity: 1; - } - } - } -} - -.osdDocTable__row--highlight { - td, - .osdDocTableRowFilterButton { - background-color: tintOrShade($euiColorPrimary, 90%, 70%); - } -} - -.osdDocTable__bar { - margin: $euiSizeXS $euiSizeXS 0; -} - -.osdDocTable__bar--footer { - position: relative; - margin: -($euiSize * 3) $euiSizeXS 0; -} - -.osdDocTable__padBottom { - padding-bottom: $euiSizeXL; -} - -.osdDocTable__error { - display: flex; - flex-direction: column; - justify-content: center; - flex: 1 0 100%; - text-align: center; -} - -.truncate-by-height { - overflow: hidden; -} - -.table { - // Nesting - .table { - background-color: $euiColorEmptyShade; - } -} - -.osd-table { - // sub tables should not have a leading border - .table .table { - margin-bottom: 0; - - tr:first-child > td { - border-top: none; - } - - td.field-name { - font-weight: $euiFontWeightBold; - } - } -} - -table { - th { - i.fa-sort { - color: $euiColorLightShade; - } - - button.fa-sort-asc, - button.fa-sort-down, - i.fa-sort-asc, - i.fa-sort-down { - color: $euiColorPrimary; - } - - button.fa-sort-desc, - button.fa-sort-up, - i.fa-sort-desc, - i.fa-sort-up { - color: $euiColorPrimary; - } - } -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/actions/columns.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/actions/columns.ts deleted file mode 100644 index 877ee7db8f55..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/actions/columns.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -/** - * Helper function to provide a fallback to a single _source column if the given array of columns - * is empty, and removes _source if there are more than 1 columns given - * @param columns - */ -function buildColumns(columns: string[]) { - if (columns.length > 1 && columns.indexOf('_source') !== -1) { - return columns.filter((col) => col !== '_source'); - } else if (columns.length !== 0) { - return columns; - } - return ['_source']; -} - -export function addColumn(columns: string[], columnName: string) { - if (columns.includes(columnName)) { - return columns; - } - return buildColumns([...columns, columnName]); -} - -export function removeColumn(columns: string[], columnName: string) { - if (!columns.includes(columnName)) { - return columns; - } - return buildColumns(columns.filter((col) => col !== columnName)); -} - -export function moveColumn(columns: string[], columnName: string, newIndex: number) { - if (newIndex < 0 || newIndex >= columns.length || !columns.includes(columnName)) { - return columns; - } - const modifiedColumns = [...columns]; - modifiedColumns.splice(modifiedColumns.indexOf(columnName), 1); // remove at old index - modifiedColumns.splice(newIndex, 0, columnName); // insert before new index - return modifiedColumns; -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/_index.scss b/src/plugins/discover_legacy/public/application/angular/doc_table/components/_index.scss deleted file mode 100644 index 25065a969b9b..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import "table_header"; -@import "table_row/index"; diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/_table_header.scss b/src/plugins/discover_legacy/public/application/angular/doc_table/components/_table_header.scss deleted file mode 100644 index 7b4c14f6a856..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/_table_header.scss +++ /dev/null @@ -1,17 +0,0 @@ -.osdDocTableHeader { - white-space: nowrap; -} - -.osdDocTableHeader button { - margin-left: $euiSizeXS; -} - -.osdDocTableHeader__move, -.osdDocTableHeader__sortChange { - opacity: 0; - - &:focus, - th:hover & { - opacity: 1; - } -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap b/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap deleted file mode 100644 index 20e503fd5ff9..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_buttons.test.tsx.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`it renders ToolBarPagerButtons 1`] = ` -
- - -
-`; diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap b/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap deleted file mode 100644 index fe168c013cb1..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/__snapshots__/tool_bar_pager_text.test.tsx.snap +++ /dev/null @@ -1,10 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`it renders ToolBarPagerText without crashing 1`] = ` -
- 1–2 of 3 -
-`; diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/index.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/index.ts deleted file mode 100644 index a0f5278d7881..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { ToolBarPagerText } from './tool_bar_pager_text'; -import { ToolBarPagerButtons } from './tool_bar_pager_buttons'; - -export function createToolBarPagerTextDirective(reactDirective: any) { - return reactDirective(ToolBarPagerText); -} - -export function createToolBarPagerButtonsDirective(reactDirective: any) { - return reactDirective(ToolBarPagerButtons); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_buttons.test.tsx b/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_buttons.test.tsx deleted file mode 100644 index 2ac06b2b6ebf..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_buttons.test.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mountWithIntl, shallowWithIntl } from 'test_utils/enzyme_helpers'; -import { ToolBarPagerButtons } from './tool_bar_pager_buttons'; -import { findTestSubject } from 'test_utils/helpers'; - -test('it renders ToolBarPagerButtons', () => { - const props = { - hasPreviousPage: true, - hasNextPage: true, - onPageNext: jest.fn(), - onPagePrevious: jest.fn(), - }; - const wrapper = shallowWithIntl(); - expect(wrapper).toMatchSnapshot(); -}); - -test('it renders ToolBarPagerButtons with clickable next and previous button', () => { - const props = { - hasPreviousPage: true, - hasNextPage: true, - onPageNext: jest.fn(), - onPagePrevious: jest.fn(), - }; - const wrapper = mountWithIntl(); - findTestSubject(wrapper, 'btnPrevPage').simulate('click'); - expect(props.onPagePrevious).toHaveBeenCalledTimes(1); - findTestSubject(wrapper, 'btnNextPage').simulate('click'); - expect(props.onPageNext).toHaveBeenCalledTimes(1); -}); - -test('it renders ToolBarPagerButtons with disabled next and previous button', () => { - const props = { - hasPreviousPage: false, - hasNextPage: false, - onPageNext: jest.fn(), - onPagePrevious: jest.fn(), - }; - const wrapper = mountWithIntl(); - findTestSubject(wrapper, 'btnPrevPage').simulate('click'); - expect(props.onPagePrevious).toHaveBeenCalledTimes(0); - findTestSubject(wrapper, 'btnNextPage').simulate('click'); - expect(props.onPageNext).toHaveBeenCalledTimes(0); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx b/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx deleted file mode 100644 index 04956583291c..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_buttons.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; - -interface Props { - hasPreviousPage: boolean; - hasNextPage: boolean; - onPageNext: () => void; - onPagePrevious: () => void; -} - -export function ToolBarPagerButtons(props: Props) { - return ( -
- - -
- ); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_text.test.tsx b/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_text.test.tsx deleted file mode 100644 index 4b13de634f04..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_text.test.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { renderWithIntl } from 'test_utils/enzyme_helpers'; -import { ToolBarPagerText } from './tool_bar_pager_text'; - -test('it renders ToolBarPagerText without crashing', () => { - const props = { - startItem: 1, - endItem: 2, - totalItems: 3, - }; - const wrapper = renderWithIntl(); - expect(wrapper).toMatchSnapshot(); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_text.tsx b/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_text.tsx deleted file mode 100644 index 28110891a2f9..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/pager/tool_bar_pager_text.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { FormattedMessage, I18nProvider } from '@osd/i18n/react'; - -interface Props { - startItem: number; - endItem: number; - totalItems: number; -} - -export function ToolBarPagerText({ startItem, endItem, totalItems }: Props) { - return ( - -
- -
-
- ); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/row_headers.test.js b/src/plugins/discover_legacy/public/application/angular/doc_table/components/row_headers.test.js deleted file mode 100644 index 1b0e03653d0d..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/row_headers.test.js +++ /dev/null @@ -1,508 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 angular from 'angular'; -import 'angular-mocks'; -import 'angular-sanitize'; -import 'angular-route'; -import _ from 'lodash'; -import sinon from 'sinon'; -import { getFakeRow } from 'fixtures/fake_row'; -import $ from 'jquery'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { - setScopedHistory, - setServices, - setDocViewsRegistry, - setDocViewsLinksRegistry, -} from '../../../../opensearch_dashboards_services'; -import { coreMock } from '../../../../../../../core/public/mocks'; -import { dataPluginMock } from '../../../../../../data/public/mocks'; -import { navigationPluginMock } from '../../../../../../navigation/public/mocks'; -import { getInnerAngularModule } from '../../../../get_inner_angular'; -import { createBrowserHistory } from 'history'; - -const fakeRowVals = { - time: 'time_formatted', - bytes: 'bytes_formatted', - '@timestamp': '@timestamp_formatted', - request_body: 'request_body_formatted', -}; - -describe('Doc Table', () => { - const core = coreMock.createStart(); - const dataMock = dataPluginMock.createStartContract(); - let $parentScope; - let $scope; - let $elementScope; - let timeout; - let registry = []; - - // Stub out a minimal mapping of 4 fields - let mapping; - - beforeAll(() => setScopedHistory(createBrowserHistory())); - beforeEach(() => { - angular.element.prototype.slice = jest.fn(function (index) { - return $(this).slice(index); - }); - angular.element.prototype.filter = jest.fn(function (condition) { - return $(this).filter(condition); - }); - angular.element.prototype.toggle = jest.fn(function (name) { - return $(this).toggle(name); - }); - angular.element.prototype.is = jest.fn(function (name) { - return $(this).is(name); - }); - setServices({ - uiSettings: core.uiSettings, - filterManager: dataMock.query.filterManager, - }); - - setDocViewsRegistry({ - addDocView(view) { - registry.push(view); - }, - getDocViewsSorted() { - return registry; - }, - resetRegistry: () => { - registry = []; - }, - }); - - setDocViewsLinksRegistry({ - addDocViewLink(view) { - registry.push(view); - }, - getDocViewsLinksSorted() { - return registry; - }, - resetRegistry: () => { - registry = []; - }, - }); - - getInnerAngularModule( - 'app/discover', - core, - { - data: dataMock, - navigation: navigationPluginMock.createStartContract(), - }, - coreMock.createPluginInitializerContext() - ); - angular.mock.module('app/discover'); - }); - beforeEach( - angular.mock.inject(function ($rootScope, Private, $timeout) { - $parentScope = $rootScope; - timeout = $timeout; - $parentScope.indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - mapping = $parentScope.indexPattern.fields; - - // Stub `getConverterFor` for a field in the indexPattern to return mock data. - - const convertFn = (value, type, options) => { - const fieldName = _.get(options, 'field.name', null); - return fakeRowVals[fieldName] || ''; - }; - $parentScope.indexPattern.getFormatterForField = () => ({ - convert: convertFn, - getConverterFor: () => convertFn, - }); - }) - ); - - afterEach(() => { - delete angular.element.prototype.slice; - delete angular.element.prototype.filter; - delete angular.element.prototype.toggle; - delete angular.element.prototype.is; - }); - - // Sets up the directive, take an element, and a list of properties to attach to the parent scope. - const init = function ($elem, props) { - angular.mock.inject(function ($compile) { - _.assign($parentScope, props); - const el = $compile($elem)($parentScope); - $elementScope = el.scope(); - el.scope().$digest(); - $scope = el.isolateScope(); - }); - }; - - const destroy = () => { - $scope.$destroy(); - $parentScope.$destroy(); - }; - - // For testing column removing/adding for the header and the rows - const columnTests = function (elemType, parentElem) { - test('should create a time column if the timefield is defined', () => { - const childElems = parentElem.find(elemType); - expect(childElems.length).toBe(1); - }); - - test('should be able to add and remove columns', () => { - let childElems; - - // Should include a column for toggling and the time column by default - $parentScope.columns = ['bytes']; - $elementScope.$digest(); - childElems = parentElem.find(elemType); - expect(childElems.length).toBe(2); - expect($(childElems[1]).text()).toContain('bytes'); - - $parentScope.columns = ['bytes', 'request_body']; - $elementScope.$digest(); - childElems = parentElem.find(elemType); - expect(childElems.length).toBe(3); - expect($(childElems[2]).text()).toContain('request_body'); - - $parentScope.columns = ['request_body']; - $elementScope.$digest(); - childElems = parentElem.find(elemType); - expect(childElems.length).toBe(2); - expect($(childElems[1]).text()).toContain('request_body'); - }); - - test('should create only the toggle column if there is no timeField', () => { - delete $scope.indexPattern.timeFieldName; - $scope.$digest(); - timeout.flush(); - - const childElems = parentElem.find(elemType); - expect(childElems.length).toBe(0); - }); - }; - - describe('osdTableRow', () => { - const $elem = $( - '' - ); - let row; - - beforeEach(() => { - row = getFakeRow(0, mapping); - - init($elem, { - row, - columns: [], - sorting: [], - filter: sinon.spy(), - maxLength: 50, - }); - }); - afterEach(() => { - destroy(); - }); - - describe('adding and removing columns', () => { - columnTests('[data-test-subj~="docTableField"]', $elem); - }); - - describe('details row', () => { - test('should be an empty tr by default', () => { - expect($elem.next().is('tr')).toBe(true); - expect($elem.next().text()).toBe(''); - }); - - test('should expand the detail row when the toggle arrow is clicked', () => { - $elem.children(':first-child').click(); - expect($elem.next().text()).not.toBe(''); - }); - - describe('expanded', () => { - let $details; - beforeEach(() => { - // Open the row - $scope.toggleRow(); - timeout.flush(); - $details = $elem.next(); - }); - afterEach(() => { - // Close the row - $scope.toggleRow(); - }); - - test('should be a tr with something in it', () => { - expect($details.is('tr')).toBe(true); - expect($details.text()).toBeTruthy(); - }); - }); - }); - }); - - describe('osdTableRow meta', () => { - const $elem = angular.element( - '' - ); - let row; - - beforeEach(() => { - row = getFakeRow(0, mapping); - - init($elem, { - row: row, - columns: [], - sorting: [], - filtering: sinon.spy(), - maxLength: 50, - }); - - // Open the row - $scope.toggleRow(); - $scope.$digest(); - timeout.flush(); - $elem.next(); - }); - - afterEach(() => { - destroy(); - }); - - /** this no longer works with the new plugin approach - test('should render even when the row source contains a field with the same name as a meta field', () => { - setTimeout(() => { - //this should be overridden by later changes - }, 100); - expect($details.find('tr').length).toBe(_.keys($parentScope.indexPattern.flattenHit($scope.row)).length); - }); */ - }); - - describe('row diffing', () => { - let $row; - let $scope; - let $root; - let $before; - - beforeEach( - angular.mock.inject(function ($rootScope, $compile, Private) { - $root = $rootScope; - $root.row = getFakeRow(0, mapping); - $root.columns = ['_source']; - $root.sorting = []; - $root.filtering = sinon.spy(); - $root.maxLength = 50; - $root.mapping = mapping; - $root.indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - - $row = $('').attr({ - 'osd-table-row': 'row', - columns: 'columns', - sorting: 'sorting', - filtering: 'filtering', - 'index-pattern': 'indexPattern', - }); - - $scope = $root.$new(); - $compile($row)($scope); - $root.$apply(); - - $before = $row.find('td'); - expect($before).toHaveLength(3); - expect($before.eq(0).text().trim()).toBe(''); - expect($before.eq(1).text().trim()).toMatch(/^time_formatted/); - }) - ); - - afterEach(() => { - $row.remove(); - }); - - test('handles a new column', () => { - $root.columns.push('bytes'); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(4); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - expect($after[2].outerHTML).toBe($before[2].outerHTML); - expect($after.eq(3).text().trim()).toMatch(/^bytes_formatted/); - }); - - test('handles two new columns at once', () => { - $root.columns.push('bytes'); - $root.columns.push('request_body'); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(5); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - expect($after[2].outerHTML).toBe($before[2].outerHTML); - expect($after.eq(3).text().trim()).toMatch(/^bytes_formatted/); - expect($after.eq(4).text().trim()).toMatch(/^request_body_formatted/); - }); - - test('handles three new columns in odd places', () => { - $root.columns = ['@timestamp', 'bytes', '_source', 'request_body']; - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(6); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - expect($after.eq(2).text().trim()).toMatch(/^@timestamp_formatted/); - expect($after.eq(3).text().trim()).toMatch(/^bytes_formatted/); - expect($after[4].outerHTML).toBe($before[2].outerHTML); - expect($after.eq(5).text().trim()).toMatch(/^request_body_formatted/); - }); - - test('handles a removed column', () => { - _.pull($root.columns, '_source'); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(2); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - }); - - test('handles two removed columns', () => { - // first add a column - $root.columns.push('@timestamp'); - $root.$apply(); - - const $mid = $row.find('td'); - expect($mid).toHaveLength(4); - - $root.columns.pop(); - $root.columns.pop(); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(2); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - }); - - test('handles three removed random columns', () => { - // first add two column - $root.columns.push('@timestamp', 'bytes'); - $root.$apply(); - - const $mid = $row.find('td'); - expect($mid).toHaveLength(5); - - $root.columns[0] = false; // _source - $root.columns[2] = false; // bytes - $root.columns = $root.columns.filter(Boolean); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(3); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - expect($after.eq(2).text().trim()).toMatch(/^@timestamp_formatted/); - }); - - test('handles two columns with the same content', () => { - const tempVal = fakeRowVals.request_body; - fakeRowVals.request_body = 'bytes_formatted'; - - $root.columns.length = 0; - $root.columns.push('bytes'); - $root.columns.push('request_body'); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(4); - expect($after.eq(2).text().trim()).toMatch(/^bytes_formatted/); - expect($after.eq(3).text().trim()).toMatch(/^bytes_formatted/); - fakeRowVals.request_body = tempVal; - }); - - test('handles two columns swapping position', () => { - $root.columns.push('bytes'); - $root.$apply(); - - const $mid = $row.find('td'); - expect($mid).toHaveLength(4); - - $root.columns.reverse(); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(4); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - expect($after[2].outerHTML).toBe($mid[3].outerHTML); - expect($after[3].outerHTML).toBe($mid[2].outerHTML); - }); - - test('handles four columns all reversing position', () => { - $root.columns.push('bytes', 'response', '@timestamp'); - $root.$apply(); - - const $mid = $row.find('td'); - expect($mid).toHaveLength(6); - - $root.columns.reverse(); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(6); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - expect($after[2].outerHTML).toBe($mid[5].outerHTML); - expect($after[3].outerHTML).toBe($mid[4].outerHTML); - expect($after[4].outerHTML).toBe($mid[3].outerHTML); - expect($after[5].outerHTML).toBe($mid[2].outerHTML); - }); - - test('handles multiple columns with the same name', () => { - $root.columns.push('bytes', 'bytes', 'bytes'); - $root.$apply(); - - const $after = $row.find('td'); - expect($after).toHaveLength(6); - expect($after[0].outerHTML).toBe($before[0].outerHTML); - expect($after[1].outerHTML).toBe($before[1].outerHTML); - expect($after[2].outerHTML).toBe($before[2].outerHTML); - expect($after.eq(3).text().trim()).toMatch(/^bytes_formatted/); - expect($after.eq(4).text().trim()).toMatch(/^bytes_formatted/); - expect($after.eq(5).text().trim()).toMatch(/^bytes_formatted/); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header.ts deleted file mode 100644 index 1c60685d279e..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { TableHeader } from './table_header/table_header'; -import { getServices } from '../../../../opensearch_dashboards_services'; -import { SORT_DEFAULT_ORDER_SETTING, DOC_HIDE_TIME_COLUMN_SETTING } from '../../../../../common'; -import { UI_SETTINGS } from '../../../../../../data/public'; - -export function createTableHeaderDirective(reactDirective: any) { - const { uiSettings: config } = getServices(); - - return reactDirective( - TableHeader, - [ - ['columns', { watchDepth: 'collection' }], - ['hideTimeColumn', { watchDepth: 'value' }], - ['indexPattern', { watchDepth: 'reference' }], - ['isShortDots', { watchDepth: 'value' }], - ['onChangeSortOrder', { watchDepth: 'reference' }], - ['onMoveColumn', { watchDepth: 'reference' }], - ['onRemoveColumn', { watchDepth: 'reference' }], - ['sortOrder', { watchDepth: 'collection' }], - ], - { restrict: 'A' }, - { - hideTimeColumn: config.get(DOC_HIDE_TIME_COLUMN_SETTING, false), - isShortDots: config.get(UI_SETTINGS.SHORT_DOTS_ENABLE), - defaultSortOrder: config.get(SORT_DEFAULT_ORDER_SETTING, 'desc'), - } - ); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap b/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap deleted file mode 100644 index 2aeb8951a60a..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap +++ /dev/null @@ -1,221 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`TableHeader with time column renders correctly 1`] = ` - - - - - Time - - - - <% } %> - - \ No newline at end of file diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/details.html b/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/details.html deleted file mode 100644 index a28f1b9906cb..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/details.html +++ /dev/null @@ -1,37 +0,0 @@ - -
-
-
-
- -
-
-

-
-
-
-
- -
-
-
- -
- - diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/open.html b/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/open.html deleted file mode 100644 index d9e15c37f02c..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/open.html +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/truncate_by_height.html b/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/truncate_by_height.html deleted file mode 100644 index cf13f10e7006..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/components/table_row/truncate_by_height.html +++ /dev/null @@ -1,3 +0,0 @@ -
- <%= body %> -
\ No newline at end of file diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/create_doc_table_react.tsx b/src/plugins/discover_legacy/public/application/angular/doc_table/create_doc_table_react.tsx deleted file mode 100644 index 8b68dc7ae466..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/create_doc_table_react.tsx +++ /dev/null @@ -1,142 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 angular, { auto, ICompileService, IScope } from 'angular'; -import { render } from 'react-dom'; -import React, { useRef, useEffect } from 'react'; -import { getServices, IIndexPattern } from '../../../opensearch_dashboards_services'; -import { IndexPatternField } from '../../../../../data/common/index_patterns'; -export type AngularScope = IScope; - -export interface AngularDirective { - template: string; -} - -/** - * Compiles and injects the give angular template into the given dom node - * returns a function to cleanup the injected angular element - */ -export async function injectAngularElement( - domNode: Element, - template: string, - scopeProps: any, - getInjector: () => Promise -): Promise<() => void> { - const $injector = await getInjector(); - const rootScope: AngularScope = $injector.get('$rootScope'); - const $compile: ICompileService = $injector.get('$compile'); - const newScope = Object.assign(rootScope.$new(), scopeProps); - - const $target = angular.element(domNode); - const $element = angular.element(template); - - newScope.$apply(() => { - const linkFn = $compile($element); - $target.empty().append($element); - linkFn(newScope); - }); - - return () => { - newScope.$destroy(); - }; -} - -/** - * Converts a given legacy angular directive to a render function - * for usage in a react component. Note that the rendering is async - */ -export function convertDirectiveToRenderFn( - directive: AngularDirective, - getInjector: () => Promise -) { - return (domNode: Element, props: any) => { - let rejected = false; - - const cleanupFnPromise = injectAngularElement(domNode, directive.template, props, getInjector); - cleanupFnPromise.catch(() => { - rejected = true; - render(
error
, domNode); - }); - - return () => { - if (!rejected) { - // for cleanup - cleanupFnPromise.then((cleanup) => cleanup()); - } - }; - }; -} - -export interface DocTableLegacyProps { - columns: string[]; - searchDescription?: string; - searchTitle?: string; - onFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; - rows: Array>; - indexPattern: IIndexPattern; - minimumVisibleRows: number; - onAddColumn: (column: string) => void; - onSort: (sort: string[][]) => void; - onMoveColumn: (columns: string, newIdx: number) => void; - onRemoveColumn: (column: string) => void; - sort?: string[][]; -} - -export function DocTableLegacy(renderProps: DocTableLegacyProps) { - const renderFn = convertDirectiveToRenderFn( - { - template: ``, - }, - () => getServices().getEmbeddableInjector() - ); - const ref = useRef(null); - useEffect(() => { - if (ref && ref.current) { - return renderFn(ref.current, renderProps); - } - }, [renderFn, renderProps]); - return
; -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.html b/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.html deleted file mode 100644 index e7a66ce50299..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.html +++ /dev/null @@ -1,67 +0,0 @@ -
-
-
-
-
- {{ limitedResultsWarning }} -
- - - - -
-
-
- - - - - - -
-
- - -
- - - - - - -
- -
- -
-
- - -
- -

-

-
-
\ No newline at end of file diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.test.js b/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.test.js deleted file mode 100644 index bd087ac3547f..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.test.js +++ /dev/null @@ -1,158 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 angular from 'angular'; -import _ from 'lodash'; -import 'angular-mocks'; -import 'angular-sanitize'; -import 'angular-route'; -import { createBrowserHistory } from 'history'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import hits from 'fixtures/real_hits'; -import { coreMock } from '../../../../../../core/public/mocks'; -import { dataPluginMock } from '../../../../../data/public/mocks'; -import { navigationPluginMock } from '../../../../../navigation/public/mocks'; -import { setScopedHistory, setServices } from '../../../opensearch_dashboards_services'; -import { getInnerAngularModule } from '../../../get_inner_angular'; - -let $parentScope; - -let $scope; - -let $timeout; - -let indexPattern; - -const init = function ($elem, props) { - angular.mock.inject(function ($rootScope, $compile, _$timeout_) { - $timeout = _$timeout_; - $parentScope = $rootScope; - _.assign($parentScope, props); - - $compile($elem)($parentScope); - - // I think the prereq requires this? - $timeout(() => { - $elem.scope().$digest(); - }, 0); - - $scope = $elem.isolateScope(); - }); -}; - -const destroy = () => { - $scope.$destroy(); - $parentScope.$destroy(); -}; - -describe('docTable', () => { - const core = coreMock.createStart(); - let $elem; - - beforeAll(() => setScopedHistory(createBrowserHistory())); - beforeEach(() => { - angular.element.prototype.slice = jest.fn(() => { - return null; - }); - angular.element.prototype.filter = jest.fn(() => { - return { - remove: jest.fn(), - }; - }); - setServices({ - uiSettings: core.uiSettings, - }); - getInnerAngularModule( - 'app/discover', - core, - { - data: dataPluginMock.createStartContract(), - navigation: navigationPluginMock.createStartContract(), - }, - coreMock.createPluginInitializerContext() - ); - angular.mock.module('app/discover'); - }); - beforeEach(() => { - $elem = angular.element(` - - `); - angular.mock.inject(function (Private) { - indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider); - }); - init($elem, { - indexPattern, - hits: [...hits], - totalHitCount: hits.length, - columns: [], - sorting: ['@timestamp', 'desc'], - }); - $scope.$digest(); - }); - - afterEach(() => { - delete angular.element.prototype.slice; - delete angular.element.prototype.filter; - destroy(); - }); - - test('should compile', () => { - expect($elem.text()).toBeTruthy(); - }); - - test('should have an addRows function that increases the row count', () => { - expect($scope.addRows).toBeInstanceOf(Function); - $scope.$digest(); - expect($scope.limit).toBe(50); - $scope.addRows(); - expect($scope.limit).toBe(100); - }); - - test('should reset the row limit when results are received', () => { - $scope.limit = 100; - expect($scope.limit).toBe(100); - $scope.hits = [...hits]; - $scope.$digest(); - expect($scope.limit).toBe(50); - }); - - test('should have a header and a table element', () => { - $scope.$digest(); - - expect($elem.find('thead').length).toBe(1); - expect($elem.find('table').length).toBe(1); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.ts deleted file mode 100644 index 2c68ad4a89ff..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table.ts +++ /dev/null @@ -1,113 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 html from './doc_table.html'; -import { dispatchRenderComplete } from '../../../../../opensearch_dashboards_utils/public'; -import { SAMPLE_SIZE_SETTING } from '../../../../common'; -// @ts-ignore -import { getLimitedSearchResultsMessage } from './doc_table_strings'; -import { getServices } from '../../../opensearch_dashboards_services'; -import './index.scss'; - -export interface LazyScope extends ng.IScope { - [key: string]: any; -} - -export function createDocTableDirective(pagerFactory: any, $filter: any) { - return { - restrict: 'E', - template: html, - scope: { - sorting: '=', - columns: '=', - hits: '=', - totalHitCount: '=', - indexPattern: '=', - isLoading: '=?', - infiniteScroll: '=?', - filter: '=?', - minimumVisibleRows: '=?', - onAddColumn: '=?', - onChangeSortOrder: '=?', - onMoveColumn: '=?', - onRemoveColumn: '=?', - inspectorAdapters: '=?', - }, - link: ($scope: LazyScope, $el: JQuery) => { - $scope.persist = { - sorting: $scope.sorting, - columns: $scope.columns, - }; - - const limitTo = $filter('limitTo'); - const calculateItemsOnPage = () => { - $scope.pager.setTotalItems($scope.hits.length); - $scope.pageOfItems = limitTo($scope.hits, $scope.pager.pageSize, $scope.pager.startIndex); - }; - - $scope.limitedResultsWarning = getLimitedSearchResultsMessage( - getServices().uiSettings.get(SAMPLE_SIZE_SETTING, 500) - ); - - $scope.addRows = function () { - $scope.limit += 50; - }; - - $scope.$watch('hits', (hits: any) => { - if (!hits) return; - - // Reset infinite scroll limit - $scope.limit = $scope.minimumVisibleRows || 50; - - if (hits.length === 0) { - dispatchRenderComplete($el[0]); - } - - if ($scope.infiniteScroll) return; - $scope.pager = pagerFactory.create(hits.length, 50, 1); - calculateItemsOnPage(); - }); - - $scope.pageOfItems = []; - $scope.onPageNext = () => { - $scope.pager.nextPage(); - calculateItemsOnPage(); - }; - - $scope.onPagePrevious = () => { - $scope.pager.previousPage(); - calculateItemsOnPage(); - }; - - $scope.shouldShowLimitedResultsWarning = () => - !$scope.pager.hasNextPage && $scope.pager.totalItems < $scope.totalHitCount; - }, - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table_strings.js b/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table_strings.js deleted file mode 100644 index 4a0457638faa..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/doc_table_strings.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; - -/** - * A message letting the user know the results that have been retrieved is limited - * to a certain size. - * @param resultCount {Number} - */ -export function getLimitedSearchResultsMessage(resultCount) { - return i18n.translate('discover.docTable.limitedSearchResultLabel', { - defaultMessage: 'Limited to {resultCount} results. Refine your search.', - values: { resultCount }, - }); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/index.scss b/src/plugins/discover_legacy/public/application/angular/doc_table/index.scss deleted file mode 100644 index 5b9dc82adb16..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import "doc_table"; -@import "components/index"; diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/index.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/index.ts deleted file mode 100644 index c51ce33cc28f..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { createDocTableDirective } from './doc_table'; -export { getSort, getSortArray } from './lib/get_sort'; -export { getSortForSearchSource } from './lib/get_sort_for_search_source'; diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/infinite_scroll.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/infinite_scroll.ts deleted file mode 100644 index 2a59d94aa5c4..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/infinite_scroll.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 $ from 'jquery'; - -interface LazyScope extends ng.IScope { - [key: string]: any; -} - -export function createInfiniteScrollDirective() { - return { - restrict: 'E', - scope: { - more: '=', - }, - link: ($scope: LazyScope, $element: JQuery) => { - const $window = $(window); - let checkTimer: any; - - function onScroll() { - if (!$scope.more) return; - - const winHeight = Number($window.height()); - const winBottom = Number(winHeight) + Number($window.scrollTop()); - const offset = $element.offset(); - const elTop = offset ? offset.top : 0; - const remaining = elTop - winBottom; - - if (remaining <= winHeight * 0.5) { - $scope[$scope.$$phase ? '$eval' : '$apply'](function () { - $scope.more(); - }); - } - } - - function scheduleCheck() { - if (checkTimer) return; - checkTimer = setTimeout(function () { - checkTimer = null; - onScroll(); - }, 50); - } - - $window.on('scroll', scheduleCheck); - $scope.$on('$destroy', function () { - clearTimeout(checkTimer); - $window.off('scroll', scheduleCheck); - }); - scheduleCheck(); - }, - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_default_sort.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_default_sort.ts deleted file mode 100644 index d22c963d219c..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_default_sort.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { IndexPattern } from '../../../../opensearch_dashboards_services'; -// @ts-ignore -import { isSortable } from './get_sort'; -import { SortOrder } from '../components/table_header/helpers'; - -/** - * use in case the user didn't manually sort. - * the default sort is returned depending of the index pattern - */ -export function getDefaultSort( - indexPattern: IndexPattern, - defaultSortOrder: string = 'desc' -): SortOrder[] { - if (indexPattern.timeFieldName && isSortable(indexPattern.timeFieldName, indexPattern)) { - return [[indexPattern.timeFieldName, defaultSortOrder]]; - } else { - return [['_score', defaultSortOrder]]; - } -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort.test.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort.test.ts deleted file mode 100644 index 30c302bccd72..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getSort, getSortArray } from './get_sort'; -// @ts-ignore -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { IndexPattern } from '../../../../opensearch_dashboards_services'; - -describe('docTable', function () { - let indexPattern: IndexPattern; - - beforeEach(() => { - indexPattern = FixturesStubbedLogstashIndexPatternProvider() as IndexPattern; - }); - - describe('getSort function', function () { - test('should be a function', function () { - expect(typeof getSort === 'function').toBeTruthy(); - }); - - test('should return an array of objects', function () { - expect(getSort([['bytes', 'desc']], indexPattern)).toEqual([{ bytes: 'desc' }]); - - delete indexPattern.timeFieldName; - expect(getSort([['bytes', 'desc']], indexPattern)).toEqual([{ bytes: 'desc' }]); - }); - - test('should passthrough arrays of objects', () => { - expect(getSort([{ bytes: 'desc' }], indexPattern)).toEqual([{ bytes: 'desc' }]); - }); - - test('should return an empty array when passed an unsortable field', function () { - expect(getSort([['non-sortable', 'asc']], indexPattern)).toEqual([]); - expect(getSort([['lol_nope', 'asc']], indexPattern)).toEqual([]); - - delete indexPattern.timeFieldName; - expect(getSort([['non-sortable', 'asc']], indexPattern)).toEqual([]); - }); - - test('should return an empty array ', function () { - expect(getSort([], indexPattern)).toEqual([]); - expect(getSort([['foo', 'bar']], indexPattern)).toEqual([]); - expect(getSort([{ foo: 'bar' }], indexPattern)).toEqual([]); - }); - - test('should convert a legacy sort to an array of objects', function () { - expect(getSort(['foo', 'desc'], indexPattern)).toEqual([{ foo: 'desc' }]); - expect(getSort(['foo', 'asc'], indexPattern)).toEqual([{ foo: 'asc' }]); - }); - }); - - describe('getSortArray function', function () { - test('should have an array method', function () { - expect(getSortArray).toBeInstanceOf(Function); - }); - - test('should return an array of arrays for sortable fields', function () { - expect(getSortArray([['bytes', 'desc']], indexPattern)).toEqual([['bytes', 'desc']]); - }); - - test('should return an array of arrays from an array of elasticsearch sort objects', function () { - expect(getSortArray([{ bytes: 'desc' }], indexPattern)).toEqual([['bytes', 'desc']]); - }); - - test('should sort by an empty array when an unsortable field is given', function () { - expect(getSortArray([{ 'non-sortable': 'asc' }], indexPattern)).toEqual([]); - expect(getSortArray([{ lol_nope: 'asc' }], indexPattern)).toEqual([]); - - delete indexPattern.timeFieldName; - expect(getSortArray([{ 'non-sortable': 'asc' }], indexPattern)).toEqual([]); - }); - - test('should return an empty array when passed an empty sort array', () => { - expect(getSortArray([], indexPattern)).toEqual([]); - - delete indexPattern.timeFieldName; - expect(getSortArray([], indexPattern)).toEqual([]); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort.ts deleted file mode 100644 index 2a65d7be5de1..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { IndexPattern } from '../../../../../../data/public'; - -export type SortPairObj = Record; -export type SortPairArr = [string, string]; -export type SortPair = SortPairArr | SortPairObj; -export type SortInput = SortPair | SortPair[]; - -export function isSortable(fieldName: string, indexPattern: IndexPattern) { - const field = indexPattern.getFieldByName(fieldName); - return field && field.sortable; -} - -function createSortObject( - sortPair: SortInput, - indexPattern: IndexPattern -): SortPairObj | undefined { - if ( - Array.isArray(sortPair) && - sortPair.length === 2 && - isSortable(String(sortPair[0]), indexPattern) - ) { - const [field, direction] = sortPair as SortPairArr; - return { [field]: direction }; - } else if (_.isPlainObject(sortPair) && isSortable(Object.keys(sortPair)[0], indexPattern)) { - return sortPair as SortPairObj; - } -} - -export function isLegacySort(sort: SortPair[] | SortPair): sort is SortPair { - return ( - sort.length === 2 && typeof sort[0] === 'string' && (sort[1] === 'desc' || sort[1] === 'asc') - ); -} - -/** - * Take a sorting array and make it into an object - * @param {array} sort two dimensional array [[fieldToSort, directionToSort]] - * or an array of objects [{fieldToSort: directionToSort}] - * @param {object} indexPattern used for determining default sort - * @returns Array<{object}> an array of sort objects - */ -export function getSort(sort: SortPair[] | SortPair, indexPattern: IndexPattern): SortPairObj[] { - if (Array.isArray(sort)) { - if (isLegacySort(sort)) { - // To stay compatible with legacy sort, which just supported a single sort field - return [{ [sort[0]]: sort[1] }]; - } - return sort - .map((sortPair: SortPair) => createSortObject(sortPair, indexPattern)) - .filter((sortPairObj) => typeof sortPairObj === 'object') as SortPairObj[]; - } - return []; -} - -/** - * compared to getSort it doesn't return an array of objects, it returns an array of arrays - * [[fieldToSort: directionToSort]] - */ -export function getSortArray(sort: SortPair[], indexPattern: IndexPattern) { - return getSort(sort, indexPattern).map((sortPair) => Object.entries(sortPair).pop()); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort_for_search_source.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort_for_search_source.ts deleted file mode 100644 index f83c764565c5..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/get_sort_for_search_source.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { OpenSearchQuerySortValue, IndexPattern } from '../../../../opensearch_dashboards_services'; -import { SortOrder } from '../components/table_header/helpers'; -import { getSort } from './get_sort'; -import { getDefaultSort } from './get_default_sort'; - -/** - * Prepares sort for search source, that's sending the request to OpenSearch - * - Adds default sort if necessary - * - Handles the special case when there's sorting by date_nanos typed fields - * the addon of the numeric_type guarantees the right sort order - * when there are indices with date and indices with date_nanos field - */ -export function getSortForSearchSource( - sort?: SortOrder[], - indexPattern?: IndexPattern, - defaultDirection: string = 'desc' -): OpenSearchQuerySortValue[] { - if (!sort || !indexPattern) { - return []; - } else if (Array.isArray(sort) && sort.length === 0) { - sort = getDefaultSort(indexPattern, defaultDirection); - } - const { timeFieldName } = indexPattern; - return getSort(sort, indexPattern).map((sortPair: Record) => { - if (indexPattern.isTimeNanosBased() && timeFieldName && sortPair[timeFieldName]) { - return { - [timeFieldName]: { - order: sortPair[timeFieldName], - numeric_type: 'date_nanos', - }, - } as OpenSearchQuerySortValue; - } - return sortPair as OpenSearchQuerySortValue; - }); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/index.js b/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/index.js deleted file mode 100644 index e400b3b52226..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/index.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 './pager_factory'; -export { Pager } from './pager'; diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/pager.js b/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/pager.js deleted file mode 100644 index 55b8c670317a..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/pager.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -function clamp(val, min, max) { - return Math.min(Math.max(min, val), max); -} - -export class Pager { - constructor(totalItems, pageSize, startingPage) { - this.currentPage = startingPage; - this.totalItems = totalItems; - this.pageSize = pageSize; - this.startIndex = 0; - this.updateMeta(); - } - - get pageCount() { - return Math.ceil(this.totalItems / this.pageSize); - } - - get hasNextPage() { - return this.currentPage < this.totalPages; - } - - get hasPreviousPage() { - return this.currentPage > 1; - } - - nextPage() { - this.currentPage += 1; - this.updateMeta(); - } - - previousPage() { - this.currentPage -= 1; - this.updateMeta(); - } - - setTotalItems(count) { - this.totalItems = count; - this.updateMeta(); - } - - setPageSize(count) { - this.pageSize = count; - this.updateMeta(); - } - - updateMeta() { - this.totalPages = Math.ceil(this.totalItems / this.pageSize); - this.currentPage = clamp(this.currentPage, 1, this.totalPages); - - this.startItem = (this.currentPage - 1) * this.pageSize + 1; - this.startItem = clamp(this.startItem, 0, this.totalItems); - - this.endItem = this.startItem - 1 + this.pageSize; - this.endItem = clamp(this.endItem, 0, this.totalItems); - - this.startIndex = this.startItem - 1; - } -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/pager_factory.ts b/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/pager_factory.ts deleted file mode 100644 index febb6428e53b..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_table/lib/pager/pager_factory.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -// @ts-ignore -import { Pager } from './pager'; - -export function createPagerFactory() { - return { - create(...args: unknown[]) { - return new Pager(...args); - }, - }; -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_viewer.tsx b/src/plugins/discover_legacy/public/application/angular/doc_viewer.tsx deleted file mode 100644 index 9072594bf478..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_viewer.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { DocViewer } from '../components/doc_viewer/doc_viewer'; - -export function createDocViewerDirective(reactDirective: any) { - return reactDirective( - (props: any) => { - return ; - }, - [ - 'hit', - ['indexPattern', { watchDepth: 'reference' }], - ['filter', { watchDepth: 'reference' }], - ['columns', { watchDepth: 'collection' }], - ['onAddColumn', { watchDepth: 'reference' }], - ['onRemoveColumn', { watchDepth: 'reference' }], - ], - { - restrict: 'E', - scope: { - hit: '=', - indexPattern: '=', - filter: '=?', - columns: '=?', - onAddColumn: '=?', - onRemoveColumn: '=?', - }, - } - ); -} diff --git a/src/plugins/discover_legacy/public/application/angular/doc_viewer_links.tsx b/src/plugins/discover_legacy/public/application/angular/doc_viewer_links.tsx deleted file mode 100644 index 763a75e51300..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/doc_viewer_links.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { DocViewerLinks } from '../components/doc_viewer_links/doc_viewer_links'; - -export function createDocViewerLinksDirective(reactDirective: any) { - return reactDirective( - (props: any) => { - return ; - }, - [ - 'hit', - ['indexPattern', { watchDepth: 'reference' }], - ['columns', { watchDepth: 'collection' }], - ], - { - restrict: 'E', - scope: { - hit: '=', - indexPattern: '=', - columns: '=?', - }, - } - ); -} diff --git a/src/plugins/discover_legacy/public/application/angular/helpers/index.ts b/src/plugins/discover_legacy/public/application/angular/helpers/index.ts deleted file mode 100644 index eb569f6985d6..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/helpers/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { buildPointSeriesData } from './point_series'; diff --git a/src/plugins/discover_legacy/public/application/angular/helpers/point_series.ts b/src/plugins/discover_legacy/public/application/angular/helpers/point_series.ts deleted file mode 100644 index 34b35453cb55..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/helpers/point_series.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { uniq } from 'lodash'; -import { Duration, Moment } from 'moment'; -import { Unit } from '@elastic/datemath'; - -import { SerializedFieldFormat } from '../../../../../expressions/common/types'; - -export interface Column { - id: string; - name: string; -} - -export interface Row { - [key: string]: number | 'NaN'; -} - -export interface Table { - columns: Column[]; - rows: Row[]; -} - -interface HistogramParams { - date: true; - interval: Duration; - intervalOpenSearchValue: number; - intervalOpenSearchUnit: Unit; - format: string; - bounds: { - min: Moment; - max: Moment; - }; -} -export interface Dimension { - accessor: 0 | 1; - format: SerializedFieldFormat<{ pattern: string }>; -} - -export interface Dimensions { - x: Dimension & { params: HistogramParams }; - y: Dimension; -} - -interface Ordered { - date: true; - interval: Duration; - intervalOpenSearchUnit: string; - intervalOpenSearchValue: number; - min: Moment; - max: Moment; -} -export interface Chart { - values: Array<{ - x: number; - y: number; - }>; - xAxisOrderedValues: number[]; - xAxisFormat: Dimension['format']; - xAxisLabel: Column['name']; - yAxisLabel?: Column['name']; - ordered: Ordered; -} - -export const buildPointSeriesData = (table: Table, dimensions: Dimensions) => { - const { x, y } = dimensions; - const xAccessor = table.columns[x.accessor].id; - const yAccessor = table.columns[y.accessor].id; - const chart = {} as Chart; - - chart.xAxisOrderedValues = uniq(table.rows.map((r) => r[xAccessor] as number)); - chart.xAxisFormat = x.format; - chart.xAxisLabel = table.columns[x.accessor].name; - - const { intervalOpenSearchUnit, intervalOpenSearchValue, interval, bounds } = x.params; - chart.ordered = { - date: true, - interval, - intervalOpenSearchUnit, - intervalOpenSearchValue, - min: bounds.min, - max: bounds.max, - }; - - chart.yAxisLabel = table.columns[y.accessor].name; - - chart.values = table.rows - .filter((row) => row && row[yAccessor] !== 'NaN') - .map((row) => ({ - x: row[xAccessor] as number, - y: row[yAccessor] as number, - })); - - return chart; -}; diff --git a/src/plugins/discover_legacy/public/application/angular/index.ts b/src/plugins/discover_legacy/public/application/angular/index.ts deleted file mode 100644 index f9b905759c06..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -// required for i18nIdDirective -import 'angular-sanitize'; -// required for ngRoute -import 'angular-route'; - -import './discover'; -import './doc'; -import './context'; -import './doc_viewer'; -import './redirect'; -import './directives'; diff --git a/src/plugins/discover_legacy/public/application/angular/redirect.ts b/src/plugins/discover_legacy/public/application/angular/redirect.ts deleted file mode 100644 index d8c03e42abb7..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/redirect.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getAngularModule, getServices, getUrlTracker } from '../../opensearch_dashboards_services'; - -getAngularModule().config(($routeProvider: any) => { - $routeProvider.otherwise({ - resolveRedirectTo: ($rootScope: any) => { - const path = window.location.hash.substr(1); - getUrlTracker().restorePreviousUrl(); - $rootScope.$applyAsync(() => { - const { urlForwarding } = getServices(); - const { navigated } = urlForwarding.navigateToLegacyOpenSearchDashboardsUrl(path); - if (!navigated) { - urlForwarding.navigateToDefaultApp(); - } - }); - // prevent angular from completing the navigation - return new Promise(() => {}); - }, - }); -}); diff --git a/src/plugins/discover_legacy/public/application/angular/response_handler.js b/src/plugins/discover_legacy/public/application/angular/response_handler.js deleted file mode 100644 index 853de0086168..000000000000 --- a/src/plugins/discover_legacy/public/application/angular/response_handler.js +++ /dev/null @@ -1,131 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getServices } from '../../opensearch_dashboards_services'; -import { buildPointSeriesData } from './helpers'; - -function tableResponseHandler(table, dimensions) { - const converted = { tables: [] }; - const split = dimensions.splitColumn || dimensions.splitRow; - - if (split) { - converted.direction = dimensions.splitRow ? 'row' : 'column'; - const splitColumnIndex = split[0].accessor; - const splitColumnFormatter = getServices().data.fieldFormats.deserialize(split[0].format); - const splitColumn = table.columns[splitColumnIndex]; - const splitMap = {}; - let splitIndex = 0; - - table.rows.forEach((row, rowIndex) => { - const splitValue = row[splitColumn.id]; - - if (!splitMap.hasOwnProperty(splitValue)) { - splitMap[splitValue] = splitIndex++; - const tableGroup = { - $parent: converted, - title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`, - name: splitColumn.name, - key: splitValue, - column: splitColumnIndex, - row: rowIndex, - table, - tables: [], - }; - tableGroup.tables.push({ - $parent: tableGroup, - columns: table.columns, - rows: [], - }); - - converted.tables.push(tableGroup); - } - - const tableIndex = splitMap[splitValue]; - converted.tables[tableIndex].tables[0].rows.push(row); - }); - } else { - converted.tables.push({ - columns: table.columns, - rows: table.rows, - }); - } - - return converted; -} - -function convertTableGroup(tableGroup, convertTable) { - const tables = tableGroup.tables; - - if (!tables.length) return; - - const firstChild = tables[0]; - if (firstChild.columns) { - const chart = convertTable(firstChild); - // if chart is within a split, assign group title to its label - if (tableGroup.$parent) { - chart.label = tableGroup.title; - } - return chart; - } - - const out = {}; - let outList; - - tables.forEach(function (table) { - if (!outList) { - const direction = tableGroup.direction === 'row' ? 'rows' : 'columns'; - outList = out[direction] = []; - } - - let output; - if ((output = convertTableGroup(table, convertTable))) { - outList.push(output); - } - }); - - return out; -} - -export const discoverResponseHandler = (response, dimensions) => { - const tableGroup = tableResponseHandler(response, dimensions); - - let converted = convertTableGroup(tableGroup, (table) => { - return buildPointSeriesData(table, dimensions); - }); - if (!converted) { - // mimic a row of tables that doesn't have any tables - // https://github.com/opensearch-project/OpenSearch-Dashboards/blob/7bfb68cd24ed42b1b257682f93c50cd8d73e2520/src/kibana/components/vislib/components/zero_injection/inject_zeros.js#L32 - converted = { rows: [] }; - } - - converted.hits = response.rows.length; - - return converted; -}; diff --git a/src/plugins/discover_legacy/public/application/application.ts b/src/plugins/discover_legacy/public/application/application.ts deleted file mode 100644 index 49fd743d76ef..000000000000 --- a/src/plugins/discover_legacy/public/application/application.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 './index.scss'; -import angular from 'angular'; -import { getServices } from '../opensearch_dashboards_services'; - -/** - * Here's where Discover's inner angular is mounted and rendered - */ -export async function renderApp(moduleName: string, element: HTMLElement) { - // do not wait for fontawesome - getServices().opensearchDashboardsLegacy.loadFontAwesome(); - await import('./angular'); - const $injector = mountDiscoverApp(moduleName, element); - return () => $injector.get('$rootScope').$destroy(); -} - -function mountDiscoverApp(moduleName: string, element: HTMLElement) { - const mountpoint = document.createElement('div'); - const appWrapper = document.createElement('div'); - appWrapper.setAttribute('ng-view', ''); - mountpoint.appendChild(appWrapper); - // bootstrap angular into detached element and attach it later to - // make angular-within-angular possible - const $injector = angular.bootstrap(mountpoint, [moduleName]); - element.appendChild(mountpoint); - return $injector; -} diff --git a/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message.test.tsx b/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message.test.tsx deleted file mode 100644 index a1ef06b81cf2..000000000000 --- a/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message.test.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ReactWrapper } from 'enzyme'; -import { ContextErrorMessage } from './context_error_message'; -// @ts-ignore -import { FAILURE_REASONS, LOADING_STATUS } from '../../angular/context/query'; -import { findTestSubject } from 'test_utils/helpers'; - -describe('loading spinner', function () { - let component: ReactWrapper; - - it('ContextErrorMessage does not render on loading', () => { - component = mountWithIntl(); - expect(findTestSubject(component, 'contextErrorMessageTitle').length).toBe(0); - }); - - it('ContextErrorMessage does not render on success loading', () => { - component = mountWithIntl(); - expect(findTestSubject(component, 'contextErrorMessageTitle').length).toBe(0); - }); - - it('ContextErrorMessage renders just the title if the reason is not specifically handled', () => { - component = mountWithIntl(); - expect(findTestSubject(component, 'contextErrorMessageTitle').length).toBe(1); - expect(findTestSubject(component, 'contextErrorMessageBody').text()).toBe(''); - }); - - it('ContextErrorMessage renders the reason for unknown errors', () => { - component = mountWithIntl( - - ); - expect(findTestSubject(component, 'contextErrorMessageTitle').length).toBe(1); - expect(findTestSubject(component, 'contextErrorMessageBody').length).toBe(1); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message.tsx b/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message.tsx deleted file mode 100644 index 8fe36f592275..000000000000 --- a/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message.tsx +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiCallOut, EuiText } from '@elastic/eui'; -import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; -// @ts-ignore -import { FAILURE_REASONS, LOADING_STATUS } from '../../angular/context/query'; - -export interface ContextErrorMessageProps { - /** - * the status of the loading action - */ - status: string; - /** - * the reason of the error - */ - reason?: string; -} - -export function ContextErrorMessage({ status, reason }: ContextErrorMessageProps) { - if (status !== LOADING_STATUS.FAILED) { - return null; - } - return ( - - - } - color="danger" - iconType="alert" - data-test-subj="contextErrorMessageTitle" - > - - {reason === FAILURE_REASONS.UNKNOWN && ( - - )} - - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message_directive.ts b/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message_directive.ts deleted file mode 100644 index 077682c67d06..000000000000 --- a/src/plugins/discover_legacy/public/application/components/context_error_message/context_error_message_directive.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { ContextErrorMessage } from './context_error_message'; - -export function createContextErrorMessageDirective(reactDirective: any) { - return reactDirective(ContextErrorMessage, [ - ['status', { watchDepth: 'reference' }], - ['reason', { watchDepth: 'reference' }], - ]); -} diff --git a/src/plugins/discover_legacy/public/application/components/context_error_message/index.ts b/src/plugins/discover_legacy/public/application/components/context_error_message/index.ts deleted file mode 100644 index 99cd662ecca3..000000000000 --- a/src/plugins/discover_legacy/public/application/components/context_error_message/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { ContextErrorMessage } from './context_error_message'; -export { createContextErrorMessageDirective } from './context_error_message_directive'; diff --git a/src/plugins/discover_legacy/public/application/components/create_discover_legacy_directive.ts b/src/plugins/discover_legacy/public/application/components/create_discover_legacy_directive.ts deleted file mode 100644 index 09cc33964862..000000000000 --- a/src/plugins/discover_legacy/public/application/components/create_discover_legacy_directive.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { DiscoverLegacy } from './discover_legacy'; - -export function createDiscoverLegacyDirective(reactDirective: any) { - return reactDirective(DiscoverLegacy, [ - ['addColumn', { watchDepth: 'reference' }], - ['fetch', { watchDepth: 'reference' }], - ['fetchCounter', { watchDepth: 'reference' }], - ['fetchError', { watchDepth: 'reference' }], - ['fieldCounts', { watchDepth: 'reference' }], - ['histogramData', { watchDepth: 'reference' }], - ['hits', { watchDepth: 'reference' }], - ['indexPattern', { watchDepth: 'reference' }], - ['minimumVisibleRows', { watchDepth: 'reference' }], - ['onAddFilter', { watchDepth: 'reference' }], - ['onChangeInterval', { watchDepth: 'reference' }], - ['onMoveColumn', { watchDepth: 'reference' }], - ['onRemoveColumn', { watchDepth: 'reference' }], - ['onSetColumns', { watchDepth: 'reference' }], - ['onSkipBottomButtonClick', { watchDepth: 'reference' }], - ['onSort', { watchDepth: 'reference' }], - ['opts', { watchDepth: 'reference' }], - ['resetQuery', { watchDepth: 'reference' }], - ['resultState', { watchDepth: 'reference' }], - ['rows', { watchDepth: 'reference' }], - ['savedSearch', { watchDepth: 'reference' }], - ['searchSource', { watchDepth: 'reference' }], - ['setIndexPattern', { watchDepth: 'reference' }], - ['showSaveQuery', { watchDepth: 'reference' }], - ['state', { watchDepth: 'reference' }], - ['timefilterUpdateHandler', { watchDepth: 'reference' }], - ['timeRange', { watchDepth: 'reference' }], - ['topNavMenu', { watchDepth: 'reference' }], - ['updateQuery', { watchDepth: 'reference' }], - ['updateSavedQueryId', { watchDepth: 'reference' }], - ['vis', { watchDepth: 'reference' }], - ]); -} diff --git a/src/plugins/discover_legacy/public/application/components/discover_legacy.tsx b/src/plugins/discover_legacy/public/application/components/discover_legacy.tsx deleted file mode 100644 index d3bf5b6ffeb8..000000000000 --- a/src/plugins/discover_legacy/public/application/components/discover_legacy.tsx +++ /dev/null @@ -1,361 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { useState, useCallback, useEffect } from 'react'; -import classNames from 'classnames'; -import { EuiButtonEmpty, EuiButtonIcon, EuiCallOut, EuiLink } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; -import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; -import { IUiSettingsClient, MountPoint } from 'opensearch-dashboards/public'; -import { HitsCounter } from './hits_counter'; -import { TimechartHeader } from './timechart_header'; -import { DiscoverSidebar } from './sidebar'; -import { getServices, IndexPattern } from '../../opensearch_dashboards_services'; -// @ts-ignore -import { DiscoverNoResults } from '../angular/directives/no_results'; -import { DiscoverUninitialized } from '../angular/directives/uninitialized'; -import { DiscoverHistogram } from '../angular/directives/histogram'; -import { LoadingSpinner } from './loading_spinner/loading_spinner'; -import { DocTableLegacy } from '../angular/doc_table/create_doc_table_react'; -import { SkipBottomButton } from './skip_bottom_button'; -import { - IndexPatternField, - search, - ISearchSource, - TimeRange, - Query, - IndexPatternAttributes, -} from '../../../../data/public'; -import { Chart } from '../angular/helpers/point_series'; -import { AppState } from '../angular/discover_state'; -import { SavedSearch } from '../../saved_searches'; - -import { SavedObject } from '../../../../../core/types'; -import { Vis } from '../../../../visualizations/public'; -import { TopNavMenuData } from '../../../../navigation/public'; - -export interface DiscoverLegacyProps { - addColumn: (column: string) => void; - fetch: () => void; - fetchCounter: number; - fieldCounts: Record; - histogramData: Chart; - hits: number; - indexPattern: IndexPattern; - minimumVisibleRows: number; - onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; - onChangeInterval: (interval: string) => void; - onMoveColumn: (columns: string, newIdx: number) => void; - onRemoveColumn: (column: string) => void; - onSetColumns: (columns: string[]) => void; - onSkipBottomButtonClick: () => void; - onSort: (sort: string[][]) => void; - opts: { - savedSearch: SavedSearch; - config: IUiSettingsClient; - indexPatternList: Array>; - timefield: string; - sampleSize: number; - fixedScroll: (el: HTMLElement) => void; - setHeaderActionMenu: (menuMount: MountPoint | undefined) => void; - }; - resetQuery: () => void; - resultState: string; - rows: Array>; - searchSource: ISearchSource; - setIndexPattern: (id: string) => void; - showSaveQuery: boolean; - state: AppState; - timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; - timeRange?: { from: string; to: string }; - topNavMenu: TopNavMenuData[]; - updateQuery: (payload: { dateRange: TimeRange; query?: Query }, isUpdate?: boolean) => void; - updateSavedQueryId: (savedQueryId?: string) => void; - vis?: Vis; -} - -export function DiscoverLegacy({ - addColumn, - fetch, - fetchCounter, - fieldCounts, - histogramData, - hits, - indexPattern, - minimumVisibleRows, - onAddFilter, - onChangeInterval, - onMoveColumn, - onRemoveColumn, - onSkipBottomButtonClick, - onSort, - opts, - resetQuery, - resultState, - rows, - searchSource, - setIndexPattern, - showSaveQuery, - state, - timefilterUpdateHandler, - timeRange, - topNavMenu, - updateQuery, - updateSavedQueryId, - vis, -}: DiscoverLegacyProps) { - const [isSidebarClosed, setIsSidebarClosed] = useState(false); - const [isCallOutVisible, setIsCallOutVisible] = useState(true); - const { TopNavMenu } = getServices().navigation.ui; - const { savedSearch, indexPatternList } = opts; - const bucketAggConfig = vis?.data?.aggs?.aggs[1]; - const bucketInterval = - bucketAggConfig && search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) - ? bucketAggConfig.buckets?.getInterval() - : undefined; - const [fixedScrollEl, setFixedScrollEl] = useState(); - - const closeCallOut = () => setIsCallOutVisible(false); - - let callOut; - - if (isCallOutVisible) { - callOut = ( -
- -

- To provide feedback,{' '} - - open an issue - - . -

-
-
- ); - } - - useEffect(() => (fixedScrollEl ? opts.fixedScroll(fixedScrollEl) : undefined), [ - fixedScrollEl, - opts, - ]); - const fixedScrollRef = useCallback( - (node: HTMLElement) => { - if (node !== null) { - setFixedScrollEl(node); - } - }, - [setFixedScrollEl] - ); - const sidebarClassName = classNames({ - closed: isSidebarClosed, - }); - - const mainSectionClassName = classNames({ - 'col-md-10': !isSidebarClosed, - 'col-md-12': isSidebarClosed, - }); - - return ( - -
-

{savedSearch.title}

-
- -
-
-
-
- {!isSidebarClosed && ( -
- -
- )} - setIsSidebarClosed(!isSidebarClosed)} - data-test-subj="collapseSideBarButton" - aria-controls="discover-sidebar" - aria-expanded={isSidebarClosed ? 'false' : 'true'} - aria-label="Toggle sidebar" - className="dscCollapsibleSidebar__collapseButton euiButtonIcon--auto" - /> -
-
- {callOut} - {resultState === 'none' && ( - - )} - {resultState === 'uninitialized' && } - {/* @TODO: Solved in the Angular way to satisfy functional test - should be improved*/} - -
- -
-
- {resultState === 'ready' && ( -
- - 0 ? hits : 0} - showResetButton={!!(savedSearch && savedSearch.id)} - onResetQuery={resetQuery} - /> - {opts.timefield && ( - - )} - - {opts.timefield && ( -
- {vis && rows.length !== 0 && ( -
- -
- )} -
- )} - -
-
-

- -

- {rows && rows.length && ( -
- - - ​ - - {rows.length === opts.sampleSize && ( -
- - - window.scrollTo(0, 0)}> - - -
- )} -
- )} -
-
-
- )} -
-
-
-
-
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/doc/doc.test.tsx b/src/plugins/discover_legacy/public/application/components/doc/doc.test.tsx deleted file mode 100644 index 4a3fb740492a..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc/doc.test.tsx +++ /dev/null @@ -1,150 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { throwError, of } from 'rxjs'; -import React from 'react'; -import { act } from 'react-dom/test-utils'; -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ReactWrapper } from 'enzyme'; -import { findTestSubject } from 'test_utils/helpers'; -import { Doc, DocProps } from './doc'; - -const mockSearchApi = jest.fn(); - -jest.mock('../../../opensearch_dashboards_services', () => { - let registry: any[] = []; - - return { - getServices: () => ({ - metadata: { - branch: 'test', - }, - data: { - search: { - search: mockSearchApi, - }, - }, - }), - getDocViewsRegistry: () => ({ - addDocView(view: any) { - registry.push(view); - }, - getDocViewsSorted() { - return registry; - }, - resetRegistry: () => { - registry = []; - }, - }), - getDocViewsLinksRegistry: () => ({ - addDocViewLink(view: any) { - registry.push(view); - }, - getDocViewsLinksSorted() { - return registry; - }, - resetRegistry: () => { - registry = []; - }, - }), - }; -}); - -beforeEach(() => { - jest.clearAllMocks(); -}); - -const waitForPromises = async () => - act(async () => { - await new Promise((resolve) => setTimeout(resolve)); - }); - -/** - * this works but logs ugly error messages until we're using React 16.9 - * should be adapted when we upgrade - */ -async function mountDoc(update = false, indexPatternGetter: any = null) { - const indexPattern = { - getComputedFields: () => [], - }; - const indexPatternService = { - get: indexPatternGetter ? indexPatternGetter : jest.fn(() => Promise.resolve(indexPattern)), - } as any; - - const props = { - id: '1', - index: 'index1', - indexPatternId: 'xyz', - indexPatternService, - } as DocProps; - let comp!: ReactWrapper; - await act(async () => { - comp = mountWithIntl(); - if (update) comp.update(); - }); - if (update) { - await waitForPromises(); - comp.update(); - } - return comp; -} - -describe('Test of of Discover', () => { - test('renders loading msg', async () => { - const comp = await mountDoc(); - expect(findTestSubject(comp, 'doc-msg-loading').length).toBe(1); - }); - - test('renders IndexPattern notFound msg', async () => { - const indexPatternGetter = jest.fn(() => Promise.reject({ savedObjectId: '007' })); - const comp = await mountDoc(true, indexPatternGetter); - expect(findTestSubject(comp, 'doc-msg-notFoundIndexPattern').length).toBe(1); - }); - - test('renders notFound msg', async () => { - mockSearchApi.mockImplementation(() => throwError({ status: 404 })); - const comp = await mountDoc(true); - expect(findTestSubject(comp, 'doc-msg-notFound').length).toBe(1); - }); - - test('renders error msg', async () => { - mockSearchApi.mockImplementation(() => throwError({ error: 'something else' })); - const comp = await mountDoc(true); - expect(findTestSubject(comp, 'doc-msg-error').length).toBe(1); - }); - - test('renders opensearch hit ', async () => { - mockSearchApi.mockImplementation(() => - of({ rawResponse: { hits: { total: 1, hits: [{ _id: 1, _source: { test: 1 } }] } } }) - ); - const comp = await mountDoc(true); - expect(findTestSubject(comp, 'doc-hit').length).toBe(1); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/doc/doc.tsx b/src/plugins/discover_legacy/public/application/components/doc/doc.tsx deleted file mode 100644 index 204a16d64757..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc/doc.tsx +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { FormattedMessage, I18nProvider } from '@osd/i18n/react'; -import { EuiCallOut, EuiLink, EuiLoadingSpinner, EuiPageContent } from '@elastic/eui'; -import { IndexPatternsContract } from 'src/plugins/data/public'; -import { OpenSearchRequestState, useOpenSearchDocSearch } from './use_opensearch_doc_search'; -import { DocViewer } from '../doc_viewer/doc_viewer'; - -export interface DocProps { - /** - * Id of the doc in OpenSearch - */ - id: string; - /** - * Index in OpenSearch to query - */ - index: string; - /** - * IndexPattern ID used to get IndexPattern entity - * that's used for adding additional fields (stored_fields, script_fields, docvalue_fields) - */ - indexPatternId: string; - /** - * IndexPatternService to get a given index pattern by ID - */ - indexPatternService: IndexPatternsContract; -} - -export function Doc(props: DocProps) { - const [reqState, hit, indexPattern] = useOpenSearchDocSearch(props); - return ( - - - {reqState === OpenSearchRequestState.NotFoundIndexPattern && ( - - } - /> - )} - {reqState === OpenSearchRequestState.NotFound && ( - - } - > - - - )} - - {reqState === OpenSearchRequestState.Error && ( - - } - > - {' '} - - - - - )} - - {reqState === OpenSearchRequestState.Loading && ( - - {' '} - - - )} - - {reqState === OpenSearchRequestState.Found && hit !== null && indexPattern && ( -
- -
- )} -
-
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/doc/use_opensearch_doc_search.test.tsx b/src/plugins/discover_legacy/public/application/components/doc/use_opensearch_doc_search.test.tsx deleted file mode 100644 index cb716a4f17cb..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc/use_opensearch_doc_search.test.tsx +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { renderHook, act } from '@testing-library/react-hooks'; -import { - buildSearchBody, - useOpenSearchDocSearch, - OpenSearchRequestState, -} from './use_opensearch_doc_search'; -import { DocProps } from './doc'; -import { Observable } from 'rxjs'; - -const mockSearchResult = new Observable(); - -jest.mock('../../../opensearch_dashboards_services', () => ({ - getServices: () => ({ - data: { - search: { - search: jest.fn(() => { - return mockSearchResult; - }), - }, - }, - }), -})); - -describe('Test of helper / hook', () => { - test('buildSearchBody', () => { - const indexPattern = { - getComputedFields: () => ({ storedFields: [], scriptFields: [], docvalueFields: [] }), - } as any; - const actual = buildSearchBody('1', indexPattern); - expect(actual).toMatchInlineSnapshot(` - Object { - "_source": true, - "docvalue_fields": Array [], - "query": Object { - "ids": Object { - "values": Array [ - "1", - ], - }, - }, - "script_fields": Array [], - "stored_fields": Array [], - } - `); - }); - - test('useOpenSearchDocSearch', async () => { - const indexPattern = { - getComputedFields: () => [], - }; - const indexPatternService = { - get: jest.fn(() => Promise.resolve(indexPattern)), - } as any; - const props = { - id: '1', - index: 'index1', - indexPatternId: 'xyz', - indexPatternService, - } as DocProps; - let hook; - await act(async () => { - hook = renderHook((p: DocProps) => useOpenSearchDocSearch(p), { initialProps: props }); - }); - // @ts-ignore - expect(hook.result.current).toEqual([OpenSearchRequestState.Loading, null, indexPattern]); - expect(indexPatternService.get).toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/doc/use_opensearch_doc_search.ts b/src/plugins/discover_legacy/public/application/components/doc/use_opensearch_doc_search.ts deleted file mode 100644 index b5ca9fec1c2f..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc/use_opensearch_doc_search.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { useEffect, useState } from 'react'; -import { IndexPattern, getServices } from '../../../opensearch_dashboards_services'; -import { DocProps } from './doc'; -import { OpenSearchSearchHit } from '../../doc_views/doc_views_types'; - -export enum OpenSearchRequestState { - Loading, - NotFound, - Found, - Error, - NotFoundIndexPattern, -} - -/** - * helper function to build a query body for OpenSearch - * https://opensearch.org/docs/latest/opensearch/query-dsl/index/ - */ -export function buildSearchBody(id: string, indexPattern: IndexPattern): Record { - const computedFields = indexPattern.getComputedFields(); - - return { - query: { - ids: { - values: [id], - }, - }, - stored_fields: computedFields.storedFields, - _source: true, - script_fields: computedFields.scriptFields, - docvalue_fields: computedFields.docvalueFields, - }; -} - -/** - * Custom react hook for querying a single doc in OpenSearch - */ -export function useOpenSearchDocSearch({ - id, - index, - indexPatternId, - indexPatternService, -}: DocProps): [OpenSearchRequestState, OpenSearchSearchHit | null, IndexPattern | null] { - const [indexPattern, setIndexPattern] = useState(null); - const [status, setStatus] = useState(OpenSearchRequestState.Loading); - const [hit, setHit] = useState(null); - - useEffect(() => { - async function requestData() { - try { - const indexPatternEntity = await indexPatternService.get(indexPatternId); - setIndexPattern(indexPatternEntity); - - const { rawResponse } = await getServices() - .data.search.search({ - dataSourceId: indexPatternEntity.dataSourceRef?.id, - params: { - index, - body: buildSearchBody(id, indexPatternEntity), - }, - }) - .toPromise(); - - const hits = rawResponse.hits; - - if (hits?.hits?.[0]) { - setStatus(OpenSearchRequestState.Found); - setHit(hits.hits[0]); - } else { - setStatus(OpenSearchRequestState.NotFound); - } - } catch (err) { - if (err.savedObjectId) { - setStatus(OpenSearchRequestState.NotFoundIndexPattern); - } else if (err.status === 404) { - setStatus(OpenSearchRequestState.NotFound); - } else { - setStatus(OpenSearchRequestState.Error); - } - } - } - requestData(); - }, [id, index, indexPatternId, indexPatternService]); - return [status, hit, indexPattern]; -} diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap b/src/plugins/discover_legacy/public/application/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap deleted file mode 100644 index cc1647fe264e..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap +++ /dev/null @@ -1,56 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Render with 3 different tabs 1`] = ` -
- , - "id": "osd_doc_viewer_tab_0", - "name": "Render function", - }, - Object { - "content": , - "id": "osd_doc_viewer_tab_1", - "name": "React component", - }, - Object { - "content": , - "id": "osd_doc_viewer_tab_2", - "name": "Invalid doc view", - }, - ] - } - /> -
-`; diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/__snapshots__/doc_viewer_render_tab.test.tsx.snap b/src/plugins/discover_legacy/public/application/components/doc_viewer/__snapshots__/doc_viewer_render_tab.test.tsx.snap deleted file mode 100644 index 31509659ce41..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/__snapshots__/doc_viewer_render_tab.test.tsx.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Mounting and unmounting DocViewerRenderTab 1`] = ` -[MockFunction] { - "calls": Array [ - Array [ -
, - Object { - "hit": Object {}, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": [MockFunction], - }, - ], -} -`; diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.scss b/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.scss deleted file mode 100644 index 91b66fc84297..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.scss +++ /dev/null @@ -1,72 +0,0 @@ -.osdDocViewerTable { - margin-top: $euiSizeS; -} - -.osdDocViewer { - pre, - .osdDocViewer__value { - display: inline-block; - word-break: break-all; - word-wrap: break-word; - white-space: pre-wrap; - color: $euiColorFullShade; - vertical-align: top; - padding-top: 2px; - } - - .osdDocViewer__field { - padding-top: 8px; - } - - .dscFieldName { - color: $euiColorDarkShade; - } - - td, - pre { - font-family: $euiCodeFontFamily; - } - - tr:first-child td { - border-top-color: transparent; - } - - tr:hover { - .osdDocViewer__actionButton { - opacity: 1; - } - } -} - -.osdDocViewer__buttons, -.osdDocViewer__field { - white-space: nowrap; -} - -.osdDocViewer__buttons { - width: 60px; - - // Show all icons if one is focused, - // IE doesn't support, but the fallback is just the focused button becomes visible - &:focus-within { - .osdDocViewer__actionButton { - opacity: 1; - } - } -} - -.osdDocViewer__field { - width: 160px; -} - -.osdDocViewer__actionButton { - opacity: 0; - - &:focus { - opacity: 1; - } -} - -.osdDocViewer__warning { - margin-right: $euiSizeS; -} diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.test.tsx b/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.test.tsx deleted file mode 100644 index ccab0be41ed2..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.test.tsx +++ /dev/null @@ -1,94 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mount, shallow } from 'enzyme'; -import { DocViewer } from './doc_viewer'; -import { findTestSubject } from 'test_utils/helpers'; -import { getDocViewsRegistry } from '../../../opensearch_dashboards_services'; -import { DocViewRenderProps } from '../../doc_views/doc_views_types'; - -jest.mock('../../../opensearch_dashboards_services', () => { - let registry: any[] = []; - return { - getDocViewsRegistry: () => ({ - addDocView(view: any) { - registry.push(view); - }, - getDocViewsSorted() { - return registry; - }, - resetRegistry: () => { - registry = []; - }, - }), - }; -}); - -beforeEach(() => { - (getDocViewsRegistry() as any).resetRegistry(); - jest.clearAllMocks(); -}); - -test('Render with 3 different tabs', () => { - const registry = getDocViewsRegistry(); - registry.addDocView({ order: 10, title: 'Render function', render: jest.fn() }); - registry.addDocView({ order: 20, title: 'React component', component: () =>
test
}); - registry.addDocView({ order: 30, title: 'Invalid doc view' }); - - const renderProps = { hit: {} } as DocViewRenderProps; - - const wrapper = shallow(); - - expect(wrapper).toMatchSnapshot(); -}); - -test('Render with 1 tab displaying error message', () => { - function SomeComponent() { - // this is just a placeholder - return null; - } - - const registry = getDocViewsRegistry(); - registry.addDocView({ - order: 10, - title: 'React component', - component: SomeComponent, - }); - - const renderProps = { hit: {} } as DocViewRenderProps; - const errorMsg = 'Catch me if you can!'; - - const wrapper = mount(); - const error = new Error(errorMsg); - wrapper.find(SomeComponent).simulateError(error); - const errorMsgComponent = findTestSubject(wrapper, 'docViewerError'); - expect(errorMsgComponent.text()).toMatch(new RegExp(`${errorMsg}`)); -}); diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.tsx b/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.tsx deleted file mode 100644 index d165c9bd05b8..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 './doc_viewer.scss'; -import React from 'react'; -import { EuiTabbedContent } from '@elastic/eui'; -import { getDocViewsRegistry } from '../../../opensearch_dashboards_services'; -import { DocViewerTab } from './doc_viewer_tab'; -import { DocView, DocViewRenderProps } from '../../doc_views/doc_views_types'; - -/** - * Rendering tabs with different views of 1 OpenSearch hit in Discover. - * The tabs are provided by the `docs_views` registry. - * A view can contain a React `component`, or any JS framework by using - * a `render` function. - */ -export function DocViewer(renderProps: DocViewRenderProps) { - const docViewsRegistry = getDocViewsRegistry(); - const tabs = docViewsRegistry - .getDocViewsSorted(renderProps.hit) - .map(({ title, render, component }: DocView, idx: number) => { - return { - id: `osd_doc_viewer_tab_${idx}`, - name: title, - content: ( - - ), - }; - }); - - if (!tabs.length) { - // There there's a minimum of 2 tabs active in Discover. - // This condition takes care of unit tests with 0 tabs. - return null; - } - - return ( -
- -
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_error.tsx b/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_error.tsx deleted file mode 100644 index 1cb14d191a57..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_error.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiCallOut, EuiCodeBlock } from '@elastic/eui'; -import { formatMsg, formatStack } from '../../../../../opensearch_dashboards_legacy/public'; - -interface Props { - error: Error | string; -} - -export function DocViewerError({ error }: Props) { - const errMsg = formatMsg(error); - const errStack = typeof error === 'object' ? formatStack(error) : ''; - - return ( - - {errStack && {errStack}} - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_tab.test.tsx b/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_tab.test.tsx deleted file mode 100644 index 83d857b24fc5..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_tab.test.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mount } from 'enzyme'; -import { DocViewRenderTab } from './doc_viewer_render_tab'; -import { DocViewRenderProps } from '../../doc_views/doc_views_types'; - -test('Mounting and unmounting DocViewerRenderTab', () => { - const unmountFn = jest.fn(); - const renderFn = jest.fn(() => unmountFn); - const renderProps = { - hit: {}, - }; - - const wrapper = mount( - - ); - - expect(renderFn).toMatchSnapshot(); - - wrapper.unmount(); - - expect(unmountFn).toBeCalled(); -}); diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_tab.tsx b/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_tab.tsx deleted file mode 100644 index edc7f40c5e43..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_render_tab.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { useRef, useEffect } from 'react'; -import { DocViewRenderFn, DocViewRenderProps } from '../../doc_views/doc_views_types'; - -interface Props { - render: DocViewRenderFn; - renderProps: DocViewRenderProps; -} -/** - * Responsible for rendering a tab provided by a render function. - * So any other framework can be used (E.g. legacy Angular 3rd party plugin code) - * The provided `render` function is called with a reference to the - * component's `HTMLDivElement` as 1st arg and `renderProps` as 2nd arg - */ -export function DocViewRenderTab({ render, renderProps }: Props) { - const ref = useRef(null); - useEffect(() => { - if (ref && ref.current) { - return render(ref.current, renderProps); - } - }, [render, renderProps]); - return
; -} diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_tab.tsx b/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_tab.tsx deleted file mode 100644 index 6e7a5f1ac434..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer/doc_viewer_tab.tsx +++ /dev/null @@ -1,101 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { I18nProvider } from '@osd/i18n/react'; -import { DocViewRenderTab } from './doc_viewer_render_tab'; -import { DocViewerError } from './doc_viewer_render_error'; -import { DocViewRenderFn, DocViewRenderProps } from '../../doc_views/doc_views_types'; - -interface Props { - component?: React.ComponentType; - id: number; - render?: DocViewRenderFn; - renderProps: DocViewRenderProps; - title: string; -} - -interface State { - error: Error | string; - hasError: boolean; -} -/** - * Renders the tab content of a doc view. - * Displays an error message when it encounters exceptions, thanks to - * Error Boundaries. - */ -export class DocViewerTab extends React.Component { - state = { - hasError: false, - error: '', - }; - - static getDerivedStateFromError(error: unknown) { - // Update state so the next render will show the fallback UI. - return { hasError: true, error }; - } - - shouldComponentUpdate(nextProps: Props, nextState: State) { - return ( - nextProps.renderProps.hit._id !== this.props.renderProps.hit._id || - nextProps.id !== this.props.id || - nextState.hasError - ); - } - - render() { - const { component, render, renderProps, title } = this.props; - const { hasError, error } = this.state; - - if (hasError && error) { - return ; - } else if (!render && !component) { - return ( - - ); - } - - if (render) { - // doc view is provided by a render function, e.g. for legacy Angular code - return ; - } - - // doc view is provided by a react component - - const Component = component as any; - return ( - - - - ); - } -} diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer_links/__snapshots__/doc_viewer_links.test.tsx.snap b/src/plugins/discover_legacy/public/application/components/doc_viewer_links/__snapshots__/doc_viewer_links.test.tsx.snap deleted file mode 100644 index 95fb0c377180..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer_links/__snapshots__/doc_viewer_links.test.tsx.snap +++ /dev/null @@ -1,34 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Dont Render if generateCb.hide 1`] = ` - -`; - -exports[`Render with 2 different links 1`] = ` - - - - - - - - -`; diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer_links/doc_viewer_links.test.tsx b/src/plugins/discover_legacy/public/application/components/doc_viewer_links/doc_viewer_links.test.tsx deleted file mode 100644 index 8aba555b3a37..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer_links/doc_viewer_links.test.tsx +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { shallow } from 'enzyme'; -import { DocViewerLinks } from './doc_viewer_links'; -import { getDocViewsLinksRegistry } from '../../../opensearch_dashboards_services'; -import { DocViewLinkRenderProps } from '../../doc_views_links/doc_views_links_types'; - -jest.mock('../../../opensearch_dashboards_services', () => { - let registry: any[] = []; - return { - getDocViewsLinksRegistry: () => ({ - addDocViewLink(view: any) { - registry.push(view); - }, - getDocViewsLinksSorted() { - return registry; - }, - resetRegistry: () => { - registry = []; - }, - }), - }; -}); - -beforeEach(() => { - (getDocViewsLinksRegistry() as any).resetRegistry(); - jest.clearAllMocks(); -}); - -test('Render with 2 different links', () => { - const registry = getDocViewsLinksRegistry(); - registry.addDocViewLink({ - order: 10, - label: 'generateCb link', - generateCb: () => ({ - url: 'aaa', - }), - }); - registry.addDocViewLink({ order: 20, label: 'href link', href: 'bbb' }); - - const renderProps = { hit: {} } as DocViewLinkRenderProps; - - const wrapper = shallow(); - - expect(wrapper).toMatchSnapshot(); -}); - -test('Dont Render if generateCb.hide', () => { - const registry = getDocViewsLinksRegistry(); - registry.addDocViewLink({ - order: 10, - label: 'generateCb link', - generateCb: () => ({ - url: 'aaa', - hide: true, - }), - }); - - const renderProps = { hit: {} } as DocViewLinkRenderProps; - - const wrapper = shallow(); - - expect(wrapper).toMatchSnapshot(); -}); diff --git a/src/plugins/discover_legacy/public/application/components/doc_viewer_links/doc_viewer_links.tsx b/src/plugins/discover_legacy/public/application/components/doc_viewer_links/doc_viewer_links.tsx deleted file mode 100644 index 9efb0693fde6..000000000000 --- a/src/plugins/discover_legacy/public/application/components/doc_viewer_links/doc_viewer_links.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiListGroupItem, EuiListGroupItemProps } from '@elastic/eui'; -import { getDocViewsLinksRegistry } from '../../../opensearch_dashboards_services'; -import { DocViewLinkRenderProps } from '../../doc_views_links/doc_views_links_types'; - -export function DocViewerLinks(renderProps: DocViewLinkRenderProps) { - const listItems = getDocViewsLinksRegistry() - .getDocViewsLinksSorted() - .filter((item) => !(item.generateCb && item.generateCb(renderProps)?.hide)) - .map((item) => { - const { generateCb, href, ...props } = item; - const listItem: EuiListGroupItemProps = { - 'data-test-subj': 'docTableRowAction', - ...props, - href: generateCb ? generateCb(renderProps).url : href, - }; - - return listItem; - }); - - return ( - - {listItems.map((item, index) => ( - - - - ))} - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/field_name/__snapshots__/field_name.test.tsx.snap b/src/plugins/discover_legacy/public/application/components/field_name/__snapshots__/field_name.test.tsx.snap deleted file mode 100644 index cfd81a66acae..000000000000 --- a/src/plugins/discover_legacy/public/application/components/field_name/__snapshots__/field_name.test.tsx.snap +++ /dev/null @@ -1,94 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`FieldName renders a geo field, useShortDots is set to true 1`] = ` -
-
- - - -
-
- - - t.t.test - - -
-
-`; - -exports[`FieldName renders a number field by providing a field record, useShortDots is set to false 1`] = ` -
-
- - - -
-
- - - test.test.test - - -
-
-`; - -exports[`FieldName renders a string field by providing fieldType and fieldName 1`] = ` -
-
- - - -
-
- - - test - - -
-
-`; diff --git a/src/plugins/discover_legacy/public/application/components/field_name/field_name.test.tsx b/src/plugins/discover_legacy/public/application/components/field_name/field_name.test.tsx deleted file mode 100644 index 54dc902837d0..000000000000 --- a/src/plugins/discover_legacy/public/application/components/field_name/field_name.test.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { render } from 'enzyme'; -import { FieldName } from './field_name'; - -// Note that it currently provides just 2 basic tests, there should be more, but -// the components involved will soon change -test('FieldName renders a string field by providing fieldType and fieldName', () => { - const component = render(); - expect(component).toMatchSnapshot(); -}); - -test('FieldName renders a number field by providing a field record, useShortDots is set to false', () => { - const component = render(); - expect(component).toMatchSnapshot(); -}); - -test('FieldName renders a geo field, useShortDots is set to true', () => { - const component = render( - - ); - expect(component).toMatchSnapshot(); -}); diff --git a/src/plugins/discover_legacy/public/application/components/field_name/field_name.tsx b/src/plugins/discover_legacy/public/application/components/field_name/field_name.tsx deleted file mode 100644 index bbd9ab79d0fb..000000000000 --- a/src/plugins/discover_legacy/public/application/components/field_name/field_name.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; - -import { FieldIcon, FieldIconProps } from '../../../../../opensearch_dashboards_react/public'; -import { shortenDottedString } from '../../helpers'; -import { getFieldTypeName } from './field_type_name'; - -// properties fieldType and fieldName are provided in osd_doc_view -// this should be changed when both components are deangularized -interface Props { - fieldName: string; - fieldType: string; - useShortDots?: boolean; - fieldIconProps?: Omit; - scripted?: boolean; -} - -export function FieldName({ - fieldName, - fieldType, - useShortDots, - fieldIconProps, - scripted = false, -}: Props) { - const typeName = getFieldTypeName(fieldType); - const displayName = useShortDots ? shortenDottedString(fieldName) : fieldName; - - return ( - - - - - - - {displayName} - - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/field_name/field_type_name.ts b/src/plugins/discover_legacy/public/application/components/field_name/field_type_name.ts deleted file mode 100644 index 38b18792d3e4..000000000000 --- a/src/plugins/discover_legacy/public/application/components/field_name/field_type_name.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; - -export function getFieldTypeName(type: string) { - switch (type) { - case 'boolean': - return i18n.translate('discover.fieldNameIcons.booleanAriaLabel', { - defaultMessage: 'Boolean field', - }); - case 'conflict': - return i18n.translate('discover.fieldNameIcons.conflictFieldAriaLabel', { - defaultMessage: 'Conflicting field', - }); - case 'date': - return i18n.translate('discover.fieldNameIcons.dateFieldAriaLabel', { - defaultMessage: 'Date field', - }); - case 'geo_point': - return i18n.translate('discover.fieldNameIcons.geoPointFieldAriaLabel', { - defaultMessage: 'Geo point field', - }); - case 'geo_shape': - return i18n.translate('discover.fieldNameIcons.geoShapeFieldAriaLabel', { - defaultMessage: 'Geo shape field', - }); - case 'ip': - return i18n.translate('discover.fieldNameIcons.ipAddressFieldAriaLabel', { - defaultMessage: 'IP address field', - }); - case 'murmur3': - return i18n.translate('discover.fieldNameIcons.murmur3FieldAriaLabel', { - defaultMessage: 'Murmur3 field', - }); - case 'number': - return i18n.translate('discover.fieldNameIcons.numberFieldAriaLabel', { - defaultMessage: 'Number field', - }); - case 'source': - // Note that this type is currently not provided, type for _source is undefined - return i18n.translate('discover.fieldNameIcons.sourceFieldAriaLabel', { - defaultMessage: 'Source field', - }); - case 'string': - return i18n.translate('discover.fieldNameIcons.stringFieldAriaLabel', { - defaultMessage: 'String field', - }); - case 'nested': - return i18n.translate('discover.fieldNameIcons.nestedFieldAriaLabel', { - defaultMessage: 'Nested field', - }); - default: - return i18n.translate('discover.fieldNameIcons.unknownFieldAriaLabel', { - defaultMessage: 'Unknown field', - }); - } -} diff --git a/src/plugins/discover_legacy/public/application/components/help_menu/help_menu_util.js b/src/plugins/discover_legacy/public/application/components/help_menu/help_menu_util.js deleted file mode 100644 index 39ea94046d7c..000000000000 --- a/src/plugins/discover_legacy/public/application/components/help_menu/help_menu_util.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; -import { getServices } from '../../../opensearch_dashboards_services'; -const { docLinks } = getServices(); - -export function addHelpMenuToAppChrome(chrome) { - chrome.setHelpExtension({ - appName: i18n.translate('discover.helpMenu.appName', { - defaultMessage: 'Discover', - }), - links: [ - { - linkType: 'documentation', - href: `${docLinks.links.opensearchDashboards.introduction}`, - }, - ], - }); -} diff --git a/src/plugins/discover_legacy/public/application/components/hits_counter/hits_counter.test.tsx b/src/plugins/discover_legacy/public/application/components/hits_counter/hits_counter.test.tsx deleted file mode 100644 index 998ababbc47f..000000000000 --- a/src/plugins/discover_legacy/public/application/components/hits_counter/hits_counter.test.tsx +++ /dev/null @@ -1,80 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ReactWrapper } from 'enzyme'; -import { HitsCounter, HitsCounterProps } from './hits_counter'; -import { findTestSubject } from 'test_utils/helpers'; - -describe('hits counter', function () { - let props: HitsCounterProps; - let component: ReactWrapper; - - beforeAll(() => { - props = { - onResetQuery: jest.fn(), - showResetButton: true, - hits: 2, - }; - }); - - it('HitsCounter renders a button by providing the showResetButton property', () => { - component = mountWithIntl(); - expect(findTestSubject(component, 'resetSavedSearch').length).toBe(1); - }); - - it('HitsCounter not renders a button when the showResetButton property is false', () => { - component = mountWithIntl( - - ); - expect(findTestSubject(component, 'resetSavedSearch').length).toBe(0); - }); - - it('expect to render the number of hits', function () { - component = mountWithIntl(); - const hits = findTestSubject(component, 'discoverQueryHits'); - expect(hits.text()).toBe('2'); - }); - - it('expect to render 1,899 hits if 1899 hits given', function () { - component = mountWithIntl( - - ); - const hits = findTestSubject(component, 'discoverQueryHits'); - expect(hits.text()).toBe('1,899'); - }); - - it('should reset query', function () { - component = mountWithIntl(); - findTestSubject(component, 'resetSavedSearch').simulate('click'); - expect(props.onResetQuery).toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/hits_counter/hits_counter.tsx b/src/plugins/discover_legacy/public/application/components/hits_counter/hits_counter.tsx deleted file mode 100644 index 3355b733202b..000000000000 --- a/src/plugins/discover_legacy/public/application/components/hits_counter/hits_counter.tsx +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; -import { i18n } from '@osd/i18n'; -import { formatNumWithCommas } from '../../helpers'; - -export interface HitsCounterProps { - /** - * the number of query hits - */ - hits: number; - /** - * displays the reset button - */ - showResetButton: boolean; - /** - * resets the query - */ - onResetQuery: () => void; -} - -export function HitsCounter({ hits, showResetButton, onResetQuery }: HitsCounterProps) { - return ( - - - - - {formatNumWithCommas(hits)}{' '} - - - - {showResetButton && ( - - - - - - )} - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/hits_counter/index.ts b/src/plugins/discover_legacy/public/application/components/hits_counter/index.ts deleted file mode 100644 index 213cf96e0cc8..000000000000 --- a/src/plugins/discover_legacy/public/application/components/hits_counter/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { HitsCounter } from './hits_counter'; diff --git a/src/plugins/discover_legacy/public/application/components/json_code_block/__snapshots__/json_code_block.test.tsx.snap b/src/plugins/discover_legacy/public/application/components/json_code_block/__snapshots__/json_code_block.test.tsx.snap deleted file mode 100644 index 3897e22c50f1..000000000000 --- a/src/plugins/discover_legacy/public/application/components/json_code_block/__snapshots__/json_code_block.test.tsx.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`returns the \`JsonCodeEditor\` component 1`] = ` - - { - "_index": "test", - "_type": "doc", - "_id": "foo", - "_score": 1, - "_source": { - "test": 123 - } -} - -`; diff --git a/src/plugins/discover_legacy/public/application/components/json_code_block/json_code_block.test.tsx b/src/plugins/discover_legacy/public/application/components/json_code_block/json_code_block.test.tsx deleted file mode 100644 index 2cb700b4d2ac..000000000000 --- a/src/plugins/discover_legacy/public/application/components/json_code_block/json_code_block.test.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { shallow } from 'enzyme'; -import { JsonCodeBlock } from './json_code_block'; -import { IndexPattern } from '../../../../../data/public'; - -it('returns the `JsonCodeEditor` component', () => { - const props = { - hit: { _index: 'test', _type: 'doc', _id: 'foo', _score: 1, _source: { test: 123 } }, - columns: [], - indexPattern: {} as IndexPattern, - filter: jest.fn(), - onAddColumn: jest.fn(), - onRemoveColumn: jest.fn(), - }; - expect(shallow()).toMatchSnapshot(); -}); diff --git a/src/plugins/discover_legacy/public/application/components/json_code_block/json_code_block.tsx b/src/plugins/discover_legacy/public/application/components/json_code_block/json_code_block.tsx deleted file mode 100644 index f33cae438cb2..000000000000 --- a/src/plugins/discover_legacy/public/application/components/json_code_block/json_code_block.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiCodeBlock } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; -import { DocViewRenderProps } from '../../doc_views/doc_views_types'; - -export function JsonCodeBlock({ hit }: DocViewRenderProps) { - const label = i18n.translate('discover.docViews.json.codeEditorAriaLabel', { - defaultMessage: 'Read only JSON view of an opensearch document', - }); - return ( - - {JSON.stringify(hit, null, 2)} - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/loading_spinner/loading_spinner.test.tsx b/src/plugins/discover_legacy/public/application/components/loading_spinner/loading_spinner.test.tsx deleted file mode 100644 index fbc98e2550e0..000000000000 --- a/src/plugins/discover_legacy/public/application/components/loading_spinner/loading_spinner.test.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ReactWrapper } from 'enzyme'; -import { LoadingSpinner } from './loading_spinner'; -import { findTestSubject } from 'test_utils/helpers'; - -describe('loading spinner', function () { - let component: ReactWrapper; - - it('LoadingSpinner renders a Searching text and a spinner', () => { - component = mountWithIntl(); - expect(findTestSubject(component, 'loadingSpinnerText').text()).toBe('Searching'); - expect(findTestSubject(component, 'loadingSpinner').length).toBe(1); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/loading_spinner/loading_spinner.tsx b/src/plugins/discover_legacy/public/application/components/loading_spinner/loading_spinner.tsx deleted file mode 100644 index 697c7a136d60..000000000000 --- a/src/plugins/discover_legacy/public/application/components/loading_spinner/loading_spinner.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiLoadingSpinner, EuiTitle, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@osd/i18n/react'; - -export function LoadingSpinner() { - return ( - <> - -

- -

-
- - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/__snapshots__/discover_index_pattern.test.tsx.snap b/src/plugins/discover_legacy/public/application/components/sidebar/__snapshots__/discover_index_pattern.test.tsx.snap deleted file mode 100644 index 42c11152e263..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/__snapshots__/discover_index_pattern.test.tsx.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DiscoverIndexPattern Invalid props dont cause an exception: "" 1`] = `""`; diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/change_indexpattern.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/change_indexpattern.tsx deleted file mode 100644 index 553031f06721..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/change_indexpattern.tsx +++ /dev/null @@ -1,131 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; -import React, { useState } from 'react'; -import { - EuiButtonEmpty, - EuiPopover, - EuiPopoverTitle, - EuiSelectable, - EuiButtonEmptyProps, -} from '@elastic/eui'; -import { EuiSelectableProps } from '@elastic/eui/src/components/selectable/selectable'; -import { IndexPatternRef } from './types'; - -export type ChangeIndexPatternTriggerProps = EuiButtonEmptyProps & { - label: string; - title?: string; -}; - -export function ChangeIndexPattern({ - indexPatternRefs, - indexPatternId, - onChangeIndexPattern, - trigger, - selectableProps, -}: { - trigger: ChangeIndexPatternTriggerProps; - indexPatternRefs: IndexPatternRef[]; - onChangeIndexPattern: (newId: string) => void; - indexPatternId?: string; - selectableProps?: EuiSelectableProps; -}) { - const [isPopoverOpen, setPopoverIsOpen] = useState(false); - - const createTrigger = function () { - const { label, title, ...rest } = trigger; - return ( - setPopoverIsOpen(!isPopoverOpen)} - {...rest} - > - {label} - - ); - }; - - return ( - setPopoverIsOpen(false)} - className="eui-textTruncate" - anchorClassName="eui-textTruncate" - display="block" - panelPaddingSize="s" - ownFocus - > -
- - {i18n.translate('discover.fieldChooser.indexPattern.changeIndexPatternTitle', { - defaultMessage: 'Change index pattern', - })} - - ({ - label: title, - key: id, - value: id, - checked: id === indexPatternId ? 'on' : undefined, - }))} - onChange={(choices) => { - const choice = (choices.find(({ checked }) => checked) as unknown) as { - value: string; - }; - onChangeIndexPattern(choice.value); - setPopoverIsOpen(false); - }} - searchProps={{ - compressed: true, - ...(selectableProps ? selectableProps.searchProps : undefined), - }} - > - {(list, search) => ( - <> - {search} - {list} - - )} - -
-
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.scss b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.scss deleted file mode 100644 index 8e1dd41f66ab..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.scss +++ /dev/null @@ -1,4 +0,0 @@ -.dscSidebarItem__fieldPopoverPanel { - min-width: 260px; - max-width: 300px; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.test.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.test.tsx deleted file mode 100644 index 1b384a4b5550..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.test.tsx +++ /dev/null @@ -1,152 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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'; -// @ts-ignore -import { findTestSubject } from '@elastic/eui/lib/test'; -// @ts-ignore -import stubbedLogstashFields from 'fixtures/logstash_fields'; -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { DiscoverField } from './discover_field'; -import { coreMock } from '../../../../../../core/public/mocks'; -import { IndexPatternField } from '../../../../../data/public'; -import { getStubIndexPattern } from '../../../../../data/public/test_utils'; - -jest.mock('../../../opensearch_dashboards_services', () => ({ - getServices: () => ({ - history: () => ({ - location: { - search: '', - }, - }), - capabilities: { - visualize: { - show: true, - }, - }, - uiSettings: { - get: (key: string) => { - if (key === 'fields:popularLimit') { - return 5; - } else if (key === 'shortDots:enable') { - return false; - } - }, - }, - }), -})); - -function getComponent({ - selected = false, - showDetails = false, - useShortDots = false, - field, -}: { - selected?: boolean; - showDetails?: boolean; - useShortDots?: boolean; - field?: IndexPatternField; -}) { - const indexPattern = getStubIndexPattern( - 'logstash-*', - (cfg: any) => cfg, - 'time', - stubbedLogstashFields(), - coreMock.createSetup() - ); - - const finalField = - field ?? - new IndexPatternField( - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'bytes' - ); - - const props = { - indexPattern, - columns: [], - field: finalField, - getDetails: jest.fn(() => ({ buckets: [], error: '', exists: 1, total: 1 })), - onAddFilter: jest.fn(), - onAddField: jest.fn(), - onRemoveField: jest.fn(), - showDetails, - selected, - useShortDots, - }; - const comp = mountWithIntl(); - return { comp, props }; -} - -describe('discover sidebar field', function () { - it('should allow selecting fields', function () { - const { comp, props } = getComponent({}); - findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); - expect(props.onAddField).toHaveBeenCalledWith('bytes'); - }); - it('should allow deselecting fields', function () { - const { comp, props } = getComponent({ selected: true }); - findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); - expect(props.onRemoveField).toHaveBeenCalledWith('bytes'); - }); - it('should trigger getDetails', function () { - const { comp, props } = getComponent({ selected: true }); - findTestSubject(comp, 'field-bytes-showDetails').simulate('click'); - expect(props.getDetails).toHaveBeenCalledWith(props.field); - }); - it('should not allow clicking on _source', function () { - const field = new IndexPatternField( - { - name: '_source', - type: '_source', - esTypes: ['_source'], - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - '_source' - ); - const { comp, props } = getComponent({ - selected: true, - field, - }); - findTestSubject(comp, 'field-_source-showDetails').simulate('click'); - expect(props.getDetails).not.toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.tsx deleted file mode 100644 index e807267435eb..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field.tsx +++ /dev/null @@ -1,245 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { useState } from 'react'; -import { EuiPopover, EuiPopoverTitle, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; -import { DiscoverFieldDetails } from './discover_field_details'; -import { FieldIcon, FieldButton } from '../../../../../opensearch_dashboards_react/public'; -import { FieldDetails } from './types'; -import { IndexPatternField, IndexPattern } from '../../../../../data/public'; -import { shortenDottedString } from '../../helpers'; -import { getFieldTypeName } from './lib/get_field_type_name'; -import './discover_field.scss'; - -export interface DiscoverFieldProps { - /** - * the selected columns displayed in the doc table in discover - */ - columns: string[]; - /** - * The displayed field - */ - field: IndexPatternField; - /** - * The currently selected index pattern - */ - indexPattern: IndexPattern; - /** - * Callback to add/select the field - */ - onAddField: (fieldName: string) => void; - /** - * Callback to add a filter to filter bar - */ - onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; - /** - * Callback to remove/deselect a the field - * @param fieldName - */ - onRemoveField: (fieldName: string) => void; - /** - * Retrieve details data for the field - */ - getDetails: (field: IndexPatternField) => FieldDetails; - /** - * Determines whether the field is selected - */ - selected?: boolean; - /** - * Determines whether the field name is shortened test.sub1.sub2 = t.s.sub2 - */ - useShortDots?: boolean; -} - -export function DiscoverField({ - columns, - field, - indexPattern, - onAddField, - onRemoveField, - onAddFilter, - getDetails, - selected, - useShortDots, -}: DiscoverFieldProps) { - const addLabelAria = i18n.translate('discover.fieldChooser.discoverField.addButtonAriaLabel', { - defaultMessage: 'Add {field} to table', - values: { field: field.name }, - }); - const removeLabelAria = i18n.translate( - 'discover.fieldChooser.discoverField.removeButtonAriaLabel', - { - defaultMessage: 'Remove {field} from table', - values: { field: field.name }, - } - ); - - const [infoIsOpen, setOpen] = useState(false); - - const toggleDisplay = (f: IndexPatternField) => { - if (selected) { - onRemoveField(f.name); - } else { - onAddField(f.name); - } - }; - - function togglePopover() { - setOpen(!infoIsOpen); - } - - function wrapOnDot(str?: string) { - // u200B is a non-width white-space character, which allows - // the browser to efficiently word-wrap right after the dot - // without us having to draw a lot of extra DOM elements, etc - return str ? str.replace(/\./g, '.\u200B') : ''; - } - - const dscFieldIcon = ( - - ); - - const fieldName = ( - - {useShortDots ? wrapOnDot(shortenDottedString(field.name)) : wrapOnDot(field.displayName)} - - ); - - let actionButton; - if (field.name !== '_source' && !selected) { - actionButton = ( - - ) => { - if (ev.type === 'click') { - ev.currentTarget.focus(); - } - ev.preventDefault(); - ev.stopPropagation(); - toggleDisplay(field); - }} - data-test-subj={`fieldToggle-${field.name}`} - aria-label={addLabelAria} - /> - - ); - } else if (field.name !== '_source' && selected) { - actionButton = ( - - ) => { - if (ev.type === 'click') { - ev.currentTarget.focus(); - } - ev.preventDefault(); - ev.stopPropagation(); - toggleDisplay(field); - }} - data-test-subj={`fieldToggle-${field.name}`} - aria-label={removeLabelAria} - /> - - ); - } - - if (field.type === '_source') { - return ( - - ); - } - - return ( - { - togglePopover(); - }} - dataTestSubj={`field-${field.name}-showDetails`} - fieldIcon={dscFieldIcon} - fieldAction={actionButton} - fieldName={fieldName} - /> - } - isOpen={infoIsOpen} - closePopover={() => setOpen(false)} - anchorPosition="rightUp" - panelClassName="dscSidebarItem__fieldPopoverPanel" - > - - {' '} - {i18n.translate('discover.fieldChooser.discoverField.fieldTopValuesLabel', { - defaultMessage: 'Top 5 values', - })} - - {infoIsOpen && ( - - )} - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_bucket.scss b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_bucket.scss deleted file mode 100644 index 90b645f70084..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_bucket.scss +++ /dev/null @@ -1,4 +0,0 @@ -.dscFieldDetails__barContainer { - // Constrains value to the flex item, and allows for truncation when necessary - min-width: 0; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_bucket.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_bucket.tsx deleted file mode 100644 index 6a4dbe295e50..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_bucket.tsx +++ /dev/null @@ -1,133 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiText, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; -import { StringFieldProgressBar } from './string_progress_bar'; -import { Bucket } from './types'; -import { IndexPatternField } from '../../../../../data/public'; -import './discover_field_bucket.scss'; - -interface Props { - bucket: Bucket; - field: IndexPatternField; - onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; -} - -export function DiscoverFieldBucket({ field, bucket, onAddFilter }: Props) { - const emptyTxt = i18n.translate('discover.fieldChooser.detailViews.emptyStringText', { - defaultMessage: 'Empty string', - }); - const addLabel = i18n.translate('discover.fieldChooser.detailViews.filterValueButtonAriaLabel', { - defaultMessage: 'Filter for {field}: "{value}"', - values: { value: bucket.value, field: field.name }, - }); - const removeLabel = i18n.translate( - 'discover.fieldChooser.detailViews.filterOutValueButtonAriaLabel', - { - defaultMessage: 'Filter out {field}: "{value}"', - values: { value: bucket.value, field: field.name }, - } - ); - - return ( - <> - - - - - - {bucket.display === '' ? emptyTxt : bucket.display} - - - - - {bucket.percent.toFixed(1)}% - - - - - - {field.filterable && ( - -
- onAddFilter(field, bucket.value, '+')} - aria-label={addLabel} - data-test-subj={`plus-${field.name}-${bucket.value}`} - style={{ - minHeight: 'auto', - minWidth: 'auto', - paddingRight: 2, - paddingLeft: 2, - paddingTop: 0, - paddingBottom: 0, - }} - className={'euiButtonIcon--auto'} - /> - onAddFilter(field, bucket.value, '-')} - aria-label={removeLabel} - data-test-subj={`minus-${field.name}-${bucket.value}`} - style={{ - minHeight: 'auto', - minWidth: 'auto', - paddingTop: 0, - paddingBottom: 0, - paddingRight: 2, - paddingLeft: 2, - }} - className={'euiButtonIcon--auto'} - /> -
-
- )} -
- - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.scss b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.scss deleted file mode 100644 index 7bf0892d0148..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.scss +++ /dev/null @@ -1,6 +0,0 @@ -.dscFieldDetails__visualizeBtn { - @include euiFontSizeXS; - - height: $euiSizeL !important; - min-width: $euiSize * 4; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.test.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.test.tsx deleted file mode 100644 index 63d5c7ace303..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.test.tsx +++ /dev/null @@ -1,312 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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'; -// @ts-ignore -import { findTestSubject } from '@elastic/eui/lib/test'; -import { act } from '@testing-library/react'; -// @ts-ignore -import stubbedLogstashFields from 'fixtures/logstash_fields'; -import { mountWithIntl, nextTick } from 'test_utils/enzyme_helpers'; -import { DiscoverFieldDetails } from './discover_field_details'; -import { coreMock } from '../../../../../../core/public/mocks'; -import { IndexPatternField } from '../../../../../data/public'; -import { getStubIndexPattern } from '../../../../../data/public/test_utils'; - -const mockGetHref = jest.fn(); -const mockGetTriggerCompatibleActions = jest.fn(); - -jest.mock('../../../opensearch_dashboards_services', () => ({ - getUiActions: () => ({ - getTriggerCompatibleActions: mockGetTriggerCompatibleActions, - }), -})); - -const indexPattern = getStubIndexPattern( - 'logstash-*', - (cfg: any) => cfg, - 'time', - stubbedLogstashFields(), - coreMock.createSetup() -); - -describe('discover sidebar field details', function () { - const defaultProps = { - columns: [], - details: { buckets: [], error: '', exists: 1, total: 1 }, - indexPattern, - onAddFilter: jest.fn(), - }; - - beforeEach(() => { - mockGetHref.mockReturnValue('/foo/bar'); - mockGetTriggerCompatibleActions.mockReturnValue([ - { - getHref: mockGetHref, - }, - ]); - }); - - function mountComponent(field: IndexPatternField, props?: Record) { - const compProps = { ...defaultProps, ...props, field }; - return mountWithIntl(); - } - - it('should render buckets if they exist', async function () { - const visualizableField = new IndexPatternField( - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'bytes' - ); - const buckets = [1, 2, 3].map((n) => ({ - display: `display-${n}`, - value: `value-${n}`, - percent: 25, - count: 100, - })); - const comp = mountComponent(visualizableField, { - details: { ...defaultProps.details, buckets }, - }); - expect(findTestSubject(comp, 'fieldVisualizeError').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualizeBucketContainer').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualizeBucketContainer').children().length).toBe( - buckets.length - ); - // Visualize link should not be rendered until async hook update - expect(findTestSubject(comp, 'fieldVisualizeLink').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualize-bytes').length).toBe(0); - - // Complete async hook - await act(async () => { - await nextTick(); - comp.update(); - }); - expect(findTestSubject(comp, 'fieldVisualizeError').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualizeBucketContainer').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualizeBucketContainer').children().length).toBe( - buckets.length - ); - expect(findTestSubject(comp, 'fieldVisualizeLink').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualize-bytes').length).toBe(1); - }); - - it('should only render buckets if they exist', async function () { - const visualizableField = new IndexPatternField( - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'bytes' - ); - const comp = mountComponent(visualizableField); - expect(findTestSubject(comp, 'fieldVisualizeContainer').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualizeError').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualizeBucketContainer').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualizeLink').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualize-bytes').length).toBe(0); - - await act(async () => { - await nextTick(); - comp.update(); - }); - - expect(findTestSubject(comp, 'fieldVisualizeContainer').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualizeError').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualizeBucketContainer').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualizeLink').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualize-bytes').length).toBe(1); - }); - - it('should render a details error', async function () { - const visualizableField = new IndexPatternField( - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'bytes' - ); - const errText = 'Some error'; - const comp = mountComponent(visualizableField, { - details: { ...defaultProps.details, error: errText }, - }); - expect(findTestSubject(comp, 'fieldVisualizeContainer').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualizeBucketContainer').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualizeError').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualizeError').text()).toBe(errText); - - await act(async () => { - await nextTick(); - comp.update(); - }); - expect(findTestSubject(comp, 'fieldVisualizeLink').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualize-bytes').length).toBe(1); - }); - - it('should handle promise rejection from isFieldVisualizable', async function () { - mockGetTriggerCompatibleActions.mockRejectedValue(new Error('Async error')); - const visualizableField = new IndexPatternField( - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'bytes' - ); - const comp = mountComponent(visualizableField); - - await act(async () => { - await nextTick(); - comp.update(); - }); - expect(findTestSubject(comp, 'fieldVisualizeLink').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualize-bytes').length).toBe(0); - }); - - it('should handle promise rejection from getVisualizeHref', async function () { - mockGetHref.mockRejectedValue(new Error('Async error')); - const visualizableField = new IndexPatternField( - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'bytes' - ); - const comp = mountComponent(visualizableField); - - await act(async () => { - await nextTick(); - comp.update(); - }); - expect(findTestSubject(comp, 'fieldVisualizeLink').length).toBe(0); - expect(findTestSubject(comp, 'fieldVisualize-bytes').length).toBe(0); - }); - - it('should enable the visualize link for a number field', async function () { - const visualizableField = new IndexPatternField( - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'bytes' - ); - const comp = mountComponent(visualizableField); - - await act(async () => { - await nextTick(); - comp.update(); - }); - expect(findTestSubject(comp, 'fieldVisualizeLink').length).toBe(1); - expect(findTestSubject(comp, 'fieldVisualize-bytes').length).toBe(1); - }); - - it('should disable the visualize link for an _id field', async function () { - expect.assertions(1); - const conflictField = new IndexPatternField( - { - name: '_id', - type: 'string', - esTypes: ['_id'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'test' - ); - const comp = mountComponent(conflictField); - - await act(async () => { - await nextTick(); - comp.update(); - }); - expect(findTestSubject(comp, 'fieldVisualize-_id').length).toBe(0); - }); - - it('should disable the visualize link for an unknown field', async function () { - const unknownField = new IndexPatternField( - { - name: 'test', - type: 'unknown', - esTypes: ['double'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - 'test' - ); - const comp = mountComponent(unknownField); - - await act(async () => { - await nextTick(); - comp.update(); - }); - expect(findTestSubject(comp, 'fieldVisualize-test').length).toBe(0); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.tsx deleted file mode 100644 index 906c173ed07d..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_details.tsx +++ /dev/null @@ -1,153 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { useState, useEffect } from 'react'; -import { EuiLink, EuiIconTip, EuiText, EuiPopoverFooter, EuiButton, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@osd/i18n/react'; -import { DiscoverFieldBucket } from './discover_field_bucket'; -import { getWarnings } from './lib/get_warnings'; -import { - triggerVisualizeActions, - isFieldVisualizable, - getVisualizeHref, -} from './lib/visualize_trigger_utils'; -import { Bucket, FieldDetails } from './types'; -import { IndexPatternField, IndexPattern } from '../../../../../data/public'; -import './discover_field_details.scss'; - -interface DiscoverFieldDetailsProps { - columns: string[]; - details: FieldDetails; - field: IndexPatternField; - indexPattern: IndexPattern; - onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; -} - -export function DiscoverFieldDetails({ - columns, - details, - field, - indexPattern, - onAddFilter, -}: DiscoverFieldDetailsProps) { - const warnings = getWarnings(field); - const [showVisualizeLink, setShowVisualizeLink] = useState(false); - const [visualizeLink, setVisualizeLink] = useState(''); - - useEffect(() => { - const checkIfVisualizable = async () => { - const visualizable = await isFieldVisualizable(field, indexPattern.id, columns).catch( - () => false - ); - - setShowVisualizeLink(visualizable); - if (visualizable) { - const href = await getVisualizeHref(field, indexPattern.id, columns).catch(() => ''); - setVisualizeLink(href || ''); - } - }; - checkIfVisualizable(); - }, [field, indexPattern.id, columns]); - - const handleVisualizeLinkClick = (event: React.MouseEvent) => { - // regular link click. let the uiActions code handle the navigation and show popup if needed - event.preventDefault(); - triggerVisualizeActions(field, indexPattern.id, columns); - }; - - return ( - <> -
- {details.error && ( - - {details.error} - - )} - - {!details.error && details.buckets.length > 0 && ( -
- {details.buckets.map((bucket: Bucket, idx: number) => ( - - ))} -
- )} - - {showVisualizeLink && visualizeLink && ( -
- - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - handleVisualizeLinkClick(e)} - href={visualizeLink} - size="s" - className="dscFieldDetails__visualizeBtn" - data-test-subj={`fieldVisualize-${field.name}`} - > - - - {warnings.length > 0 && ( - - )} -
- )} -
- {!details.error && ( - - - {!indexPattern.metaFields.includes(field.name) && !field.scripted ? ( - onAddFilter('_exists_', field.name, '+')}> - {' '} - {details.exists} - - ) : ( - {details.exists} - )}{' '} - / {details.total}{' '} - - - - )} - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_search.test.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_search.test.tsx deleted file mode 100644 index f78505e11f1e..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_search.test.tsx +++ /dev/null @@ -1,160 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { act } from 'react-dom/test-utils'; -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { findTestSubject } from 'test_utils/helpers'; -import { DiscoverFieldSearch, Props } from './discover_field_search'; -import { EuiButtonGroupProps, EuiPopover } from '@elastic/eui'; -import { ReactWrapper } from 'enzyme'; - -describe('DiscoverFieldSearch', () => { - const defaultProps = { - onChange: jest.fn(), - value: 'test', - types: ['any', 'string', '_source'], - }; - - function mountComponent(props?: Props) { - const compProps = props || defaultProps; - return mountWithIntl(); - } - - function findButtonGroup(component: ReactWrapper, id: string) { - return component.find(`[data-test-subj="${id}ButtonGroup"]`).first(); - } - - test('enter value', () => { - const component = mountComponent(); - const input = findTestSubject(component, 'fieldFilterSearchInput'); - input.simulate('change', { target: { value: 'new filter' } }); - expect(defaultProps.onChange).toBeCalledTimes(1); - }); - - test('change in active filters should change facet selection and call onChange', () => { - const onChange = jest.fn(); - const component = mountComponent({ ...defaultProps, ...{ onChange } }); - let btn = findTestSubject(component, 'toggleFieldFilterButton'); - expect(btn.hasClass('euiFacetButton--isSelected')).toBeFalsy(); - btn.simulate('click'); - const aggregatableButtonGroup = findButtonGroup(component, 'aggregatable'); - act(() => { - // @ts-ignore - (aggregatableButtonGroup.props() as EuiButtonGroupProps).onChange('aggregatable-true', null); - }); - component.update(); - btn = findTestSubject(component, 'toggleFieldFilterButton'); - expect(btn.hasClass('euiFacetButton--isSelected')).toBe(true); - expect(onChange).toBeCalledWith('aggregatable', true); - }); - - test('change in active filters should change filters count', () => { - const component = mountComponent(); - let btn = findTestSubject(component, 'toggleFieldFilterButton'); - btn.simulate('click'); - btn = findTestSubject(component, 'toggleFieldFilterButton'); - const badge = btn.find('.euiNotificationBadge'); - // no active filters - expect(badge.text()).toEqual('0'); - // change value of aggregatable select - const aggregatableButtonGroup = findButtonGroup(component, 'aggregatable'); - act(() => { - // @ts-ignore - (aggregatableButtonGroup.props() as EuiButtonGroupProps).onChange('aggregatable-true', null); - }); - component.update(); - expect(badge.text()).toEqual('1'); - // change value of searchable select - const searchableButtonGroup = findButtonGroup(component, 'searchable'); - act(() => { - // @ts-ignore - (searchableButtonGroup.props() as EuiButtonGroupProps).onChange('searchable-true', null); - }); - component.update(); - expect(badge.text()).toEqual('2'); - // change value of searchable select - act(() => { - // @ts-ignore - (searchableButtonGroup.props() as EuiButtonGroupProps).onChange('searchable-any', null); - }); - component.update(); - expect(badge.text()).toEqual('1'); - }); - - test('change in missing fields switch should not change filter count', () => { - const component = mountComponent(); - const btn = findTestSubject(component, 'toggleFieldFilterButton'); - btn.simulate('click'); - const badge = btn.find('.euiNotificationBadge'); - expect(badge.text()).toEqual('0'); - const missingSwitch = findTestSubject(component, 'missingSwitch'); - missingSwitch.simulate('change', { target: { value: false } }); - expect(badge.text()).toEqual('0'); - }); - - test('change in filters triggers onChange', () => { - const onChange = jest.fn(); - const component = mountComponent({ ...defaultProps, ...{ onChange } }); - const btn = findTestSubject(component, 'toggleFieldFilterButton'); - btn.simulate('click'); - const aggregtableButtonGroup = findButtonGroup(component, 'aggregatable'); - const missingSwitch = findTestSubject(component, 'missingSwitch'); - act(() => { - // @ts-ignore - (aggregtableButtonGroup.props() as EuiButtonGroupProps).onChange('aggregatable-true', null); - }); - missingSwitch.simulate('click'); - expect(onChange).toBeCalledTimes(2); - }); - - test('change in type filters triggers onChange with appropriate value', () => { - const onChange = jest.fn(); - const component = mountComponent({ ...defaultProps, ...{ onChange } }); - const btn = findTestSubject(component, 'toggleFieldFilterButton'); - btn.simulate('click'); - const typeSelector = findTestSubject(component, 'typeSelect'); - typeSelector.simulate('change', { target: { value: 'string' } }); - expect(onChange).toBeCalledWith('type', 'string'); - typeSelector.simulate('change', { target: { value: 'any' } }); - expect(onChange).toBeCalledWith('type', 'any'); - }); - - test('click on filter button should open and close popover', () => { - const component = mountComponent(); - const btn = findTestSubject(component, 'toggleFieldFilterButton'); - btn.simulate('click'); - let popover = component.find(EuiPopover); - expect(popover.prop('isOpen')).toBe(true); - btn.simulate('click'); - popover = component.find(EuiPopover); - expect(popover.prop('isOpen')).toBe(false); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_search.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_search.tsx deleted file mode 100644 index 4a1390cb1955..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_field_search.tsx +++ /dev/null @@ -1,313 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { OptionHTMLAttributes, ReactNode, useState } from 'react'; -import { i18n } from '@osd/i18n'; -import { - EuiFacetButton, - EuiFieldSearch, - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiPopover, - EuiPopoverFooter, - EuiPopoverTitle, - EuiSelect, - EuiSwitch, - EuiSwitchEvent, - EuiForm, - EuiFormRow, - EuiButtonGroup, - EuiOutsideClickDetector, -} from '@elastic/eui'; -import { FormattedMessage } from '@osd/i18n/react'; - -export interface State { - searchable: string; - aggregatable: string; - type: string; - missing: boolean; - [index: string]: string | boolean; -} - -export interface Props { - /** - * triggered on input of user into search field - */ - onChange: (field: string, value: string | boolean | undefined) => void; - - /** - * the input value of the user - */ - value?: string; - - /** - * types for the type filter - */ - types: string[]; -} - -/** - * Component is Discover's side bar to search of available fields - * Additionally there's a button displayed that allows the user to show/hide more filter fields - */ -export function DiscoverFieldSearch({ onChange, value, types }: Props) { - const searchPlaceholder = i18n.translate('discover.fieldChooser.searchPlaceHolder', { - defaultMessage: 'Search field names', - }); - const aggregatableLabel = i18n.translate('discover.fieldChooser.filter.aggregatableLabel', { - defaultMessage: 'Aggregatable', - }); - const searchableLabel = i18n.translate('discover.fieldChooser.filter.searchableLabel', { - defaultMessage: 'Searchable', - }); - const typeLabel = i18n.translate('discover.fieldChooser.filter.typeLabel', { - defaultMessage: 'Type', - }); - const typeOptions = types - ? types.map((type) => { - return { value: type, text: type }; - }) - : [{ value: 'any', text: 'any' }]; - - const [activeFiltersCount, setActiveFiltersCount] = useState(0); - const [isPopoverOpen, setPopoverOpen] = useState(false); - const [values, setValues] = useState({ - searchable: 'any', - aggregatable: 'any', - type: 'any', - missing: true, - }); - - if (typeof value !== 'string') { - // at initial rendering value is undefined (angular related), this catches the warning - // should be removed once all is react - return null; - } - - const filterBtnAriaLabel = isPopoverOpen - ? i18n.translate('discover.fieldChooser.toggleFieldFilterButtonHideAriaLabel', { - defaultMessage: 'Hide field filter settings', - }) - : i18n.translate('discover.fieldChooser.toggleFieldFilterButtonShowAriaLabel', { - defaultMessage: 'Show field filter settings', - }); - - const handleFacetButtonClicked = () => { - setPopoverOpen(!isPopoverOpen); - }; - - const applyFilterValue = (id: string, filterValue: string | boolean) => { - switch (filterValue) { - case 'any': - if (id !== 'type') { - onChange(id, undefined); - } else { - onChange(id, filterValue); - } - break; - case 'true': - onChange(id, true); - break; - case 'false': - onChange(id, false); - break; - default: - onChange(id, filterValue); - } - }; - - const isFilterActive = (name: string, filterValue: string | boolean) => { - return name !== 'missing' && filterValue !== 'any'; - }; - - const handleValueChange = (name: string, filterValue: string | boolean) => { - const previousValue = values[name]; - updateFilterCount(name, previousValue, filterValue); - const updatedValues = { ...values }; - updatedValues[name] = filterValue; - setValues(updatedValues); - applyFilterValue(name, filterValue); - }; - - const updateFilterCount = ( - name: string, - previousValue: string | boolean, - currentValue: string | boolean - ) => { - const previouslyFilterActive = isFilterActive(name, previousValue); - const filterActive = isFilterActive(name, currentValue); - const diff = Number(filterActive) - Number(previouslyFilterActive); - setActiveFiltersCount(activeFiltersCount + diff); - }; - - const handleMissingChange = (e: EuiSwitchEvent) => { - const missingValue = e.target.checked; - handleValueChange('missing', missingValue); - }; - - const buttonContent = ( - } - isSelected={activeFiltersCount > 0} - quantity={activeFiltersCount} - onClick={handleFacetButtonClicked} - > - - - ); - - const select = ( - id: string, - selectOptions: Array<{ text: ReactNode } & OptionHTMLAttributes>, - selectValue: string - ) => { - return ( - ) => - handleValueChange(id, e.target.value) - } - aria-label={i18n.translate('discover.fieldChooser.filter.fieldSelectorLabel', { - defaultMessage: 'Selection of {id} filter options', - values: { id }, - })} - data-test-subj={`${id}Select`} - compressed - /> - ); - }; - - const toggleButtons = (id: string) => { - return [ - { - id: `${id}-any`, - label: 'any', - }, - { - id: `${id}-true`, - label: 'yes', - }, - { - id: `${id}-false`, - label: 'no', - }, - ]; - }; - - const buttonGroup = (id: string, legend: string) => { - return ( - handleValueChange(id, optionId.replace(`${id}-`, ''))} - buttonSize="compressed" - isFullWidth - data-test-subj={`${id}ButtonGroup`} - /> - ); - }; - - const selectionPanel = ( -
- - - {buttonGroup('aggregatable', aggregatableLabel)} - - - {buttonGroup('searchable', searchableLabel)} - - - {select('type', typeOptions, values.type)} - - -
- ); - - return ( - - - - onChange('name', event.currentTarget.value)} - placeholder={searchPlaceholder} - value={value} - /> - - -
- {}} isDisabled={!isPopoverOpen}> - { - setPopoverOpen(false); - }} - button={buttonContent} - > - - {i18n.translate('discover.fieldChooser.filter.filterByTypeLabel', { - defaultMessage: 'Filter by type', - })} - - {selectionPanel} - - - - - -
-
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern.test.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern.test.tsx deleted file mode 100644 index 9298aef92cf0..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern.test.tsx +++ /dev/null @@ -1,111 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { shallowWithIntl as shallow } from 'test_utils/enzyme_helpers'; - -// @ts-ignore -import { ShallowWrapper } from 'enzyme'; -import { ChangeIndexPattern } from './change_indexpattern'; -import { SavedObject } from 'opensearch-dashboards/server'; -import { DiscoverIndexPattern } from './discover_index_pattern'; -import { EuiSelectable } from '@elastic/eui'; -import { IIndexPattern } from 'src/plugins/data/public'; - -const indexPattern = { - id: 'test1', - title: 'test1 title', -} as IIndexPattern; - -const indexPattern1 = { - id: 'test1', - attributes: { - title: 'test1 titleToDisplay', - }, -} as SavedObject; - -const indexPattern2 = { - id: 'test2', - attributes: { - title: 'test2 titleToDisplay', - }, -} as SavedObject; - -const defaultProps = { - indexPatternList: [indexPattern1, indexPattern2], - selectedIndexPattern: indexPattern, - setIndexPattern: jest.fn(async () => {}), -}; - -function getIndexPatternPickerList(instance: ShallowWrapper) { - return instance.find(ChangeIndexPattern).first().dive().find(EuiSelectable); -} - -function getIndexPatternPickerOptions(instance: ShallowWrapper) { - return getIndexPatternPickerList(instance).prop('options'); -} - -function selectIndexPatternPickerOption(instance: ShallowWrapper, selectedLabel: string) { - const options: Array<{ label: string; checked?: 'on' | 'off' }> = getIndexPatternPickerOptions( - instance - ).map((option: any) => - option.label === selectedLabel - ? { ...option, checked: 'on' } - : { ...option, checked: undefined } - ); - return getIndexPatternPickerList(instance).prop('onChange')!(options); -} - -describe('DiscoverIndexPattern', () => { - test('Invalid props dont cause an exception', () => { - const props = { - indexPatternList: null, - selectedIndexPattern: null, - setIndexPattern: jest.fn(), - } as any; - - expect(shallow()).toMatchSnapshot(`""`); - }); - test('should list all index patterns', () => { - const instance = shallow(); - - expect(getIndexPatternPickerOptions(instance)!.map((option: any) => option.label)).toEqual([ - 'test1 titleToDisplay', - 'test2 titleToDisplay', - ]); - }); - - test('should switch data panel to target index pattern', () => { - const instance = shallow(); - - selectIndexPatternPickerOption(instance, 'test2 titleToDisplay'); - expect(defaultProps.setIndexPattern).toHaveBeenCalledWith('test2'); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern.tsx deleted file mode 100644 index 95154bec1939..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { useState, useEffect } from 'react'; -import { SavedObject } from 'opensearch-dashboards/public'; -import { IIndexPattern, IndexPatternAttributes } from 'src/plugins/data/public'; -import { I18nProvider } from '@osd/i18n/react'; - -import { IndexPatternRef } from './types'; -import { ChangeIndexPattern } from './change_indexpattern'; -export interface DiscoverIndexPatternProps { - /** - * list of available index patterns, if length > 1, component offers a "change" link - */ - indexPatternList: Array>; - /** - * currently selected index pattern, due to angular issues it's undefined at first rendering - */ - selectedIndexPattern: IIndexPattern; - /** - * triggered when user selects a new index pattern - */ - setIndexPattern: (id: string) => void; -} - -/** - * Component allows you to select an index pattern in discovers side bar - */ -export function DiscoverIndexPattern({ - indexPatternList, - selectedIndexPattern, - setIndexPattern, -}: DiscoverIndexPatternProps) { - const options: IndexPatternRef[] = (indexPatternList || []).map((entity) => ({ - id: entity.id, - title: entity.attributes!.title, - })); - const { id: selectedId, title: selectedTitle } = selectedIndexPattern || {}; - - const [selected, setSelected] = useState({ - id: selectedId, - title: selectedTitle || '', - }); - useEffect(() => { - const { id, title } = selectedIndexPattern; - const indexPattern = indexPatternList.find((pattern) => pattern.id === id); - const titleToDisplay = indexPattern ? indexPattern.attributes!.title : title; - setSelected({ id, title: titleToDisplay }); - }, [indexPatternList, selectedIndexPattern]); - if (!selectedId) { - return null; - } - - return ( -
- - { - const indexPattern = options.find((pattern) => pattern.id === id); - if (indexPattern) { - setIndexPattern(id); - setSelected(indexPattern); - } - }} - /> - -
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern_title.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern_title.tsx deleted file mode 100644 index 30b50a9006c8..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_index_pattern_title.tsx +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiToolTip, EuiFlexItem, EuiFlexGroup, EuiTitle, EuiButtonEmpty } from '@elastic/eui'; - -import { FormattedMessage } from '@osd/i18n/react'; -import { i18n } from '@osd/i18n'; -export interface DiscoverIndexPatternTitleProps { - /** - * determines whether the change link is displayed - */ - isChangeable: boolean; - /** - * function triggered when the change link is clicked - */ - onChange: () => void; - /** - * title of the current index pattern - */ - title: string; -} - -/** - * Component displaying the title of the current selected index pattern - * and if changeable is true, a link is provided to change the index pattern - */ -export function DiscoverIndexPatternTitle({ - isChangeable, - onChange, - title, -}: DiscoverIndexPatternTitleProps) { - return ( - - - - -

{title}

-
-
-
- {isChangeable && ( - - - } - > - onChange()} - iconSide="right" - iconType="arrowDown" - color="text" - /> - - - )} -
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.scss b/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.scss deleted file mode 100644 index 9c80e0afa600..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.scss +++ /dev/null @@ -1,99 +0,0 @@ -.dscSidebar__container { - padding-left: 0 !important; - padding-right: 0 !important; - background-color: transparent; - border-right-color: transparent; - border-bottom-color: transparent; -} - -.dscIndexPattern__container { - display: flex; - align-items: center; - height: $euiSize * 3; - margin-top: -$euiSizeS; -} - -.dscIndexPattern__triggerButton { - @include euiTitle("xs"); - - line-height: $euiSizeXXL; -} - -.dscFieldList { - list-style: none; - margin-bottom: 0; -} - -.dscFieldListHeader { - padding: $euiSizeS $euiSizeS 0 $euiSizeS; - background-color: lightOrDarkTheme(tint($euiColorPrimary, 90%), $euiColorLightShade); -} - -.dscFieldList--popular { - background-color: lightOrDarkTheme(tint($euiColorPrimary, 90%), $euiColorLightShade); -} - -.dscFieldChooser { - padding-left: $euiSize; -} - -.dscFieldChooser__toggle { - color: $euiColorMediumShade; - margin-left: $euiSizeS !important; -} - -.dscSidebarItem { - &:hover, - &:focus-within, - &[class*="-isActive"] { - .dscSidebarItem__action { - opacity: 1; - } - } -} - -/** - * 1. Only visually hide the action, so that it's still accessible to screen readers. - * 2. When tabbed to, this element needs to be visible for keyboard accessibility. - */ -.dscSidebarItem__action { - opacity: 0; /* 1 */ - transition: none; - - &:focus { - opacity: 1; /* 2 */ - } - - font-size: $euiFontSizeXS; - padding: 2px 6px !important; - height: 22px !important; - min-width: auto !important; - - .euiButton__content { - padding: 0 4px; - } -} - -.dscFieldSearch { - padding: $euiSizeS; -} - -.dscFieldSearch__toggleButton { - width: calc(100% - #{$euiSizeS}); - color: $euiColorPrimary; - padding-left: $euiSizeXS; - margin-left: $euiSizeXS; -} - -.dscFieldSearch__filterWrapper { - flex-grow: 0; -} - -.dscFieldSearch__formWrapper { - padding: $euiSizeM; -} - -.dscFieldDetails { - color: $euiTextColor; - margin-bottom: $euiSizeS; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.test.tsx deleted file mode 100644 index fa692ca22b5b..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.test.tsx +++ /dev/null @@ -1,148 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { ReactWrapper } from 'enzyme'; -import { findTestSubject } from 'test_utils/helpers'; -// @ts-ignore -import realHits from 'fixtures/real_hits.js'; -// @ts-ignore -import stubbedLogstashFields from 'fixtures/logstash_fields'; -import { mountWithIntl } from 'test_utils/enzyme_helpers'; -import React from 'react'; -import { DiscoverSidebar, DiscoverSidebarProps } from './discover_sidebar'; -import { coreMock } from '../../../../../../core/public/mocks'; -import { IndexPatternAttributes } from '../../../../../data/common'; -import { getStubIndexPattern } from '../../../../../data/public/test_utils'; -import { SavedObject } from '../../../../../../core/types'; - -jest.mock('../../../opensearch_dashboards_services', () => ({ - getServices: () => ({ - history: () => ({ - location: { - search: '', - }, - }), - capabilities: { - visualize: { - show: true, - }, - discover: { - save: false, - }, - }, - uiSettings: { - get: (key: string) => { - if (key === 'fields:popularLimit') { - return 5; - } else if (key === 'shortDots:enable') { - return false; - } - }, - }, - }), -})); - -jest.mock('./lib/get_index_pattern_field_list', () => ({ - getIndexPatternFieldList: jest.fn((indexPattern) => indexPattern.fields), -})); - -function getCompProps() { - const indexPattern = getStubIndexPattern( - 'logstash-*', - (cfg: any) => cfg, - 'time', - stubbedLogstashFields(), - coreMock.createSetup() - ); - - // @ts-expect-error _.each() is passing additional args to flattenHit - const hits = _.each(_.cloneDeep(realHits), indexPattern.flattenHit) as Array< - Record - >; - - const indexPatternList = [ - { id: '0', attributes: { title: 'b' } } as SavedObject, - { id: '1', attributes: { title: 'a' } } as SavedObject, - { id: '2', attributes: { title: 'c' } } as SavedObject, - ]; - - const fieldCounts: Record = {}; - - for (const hit of hits) { - for (const key of Object.keys(indexPattern.flattenHit(hit))) { - fieldCounts[key] = (fieldCounts[key] || 0) + 1; - } - } - return { - columns: ['extension'], - fieldCounts, - hits, - indexPatternList, - onAddFilter: jest.fn(), - onAddField: jest.fn(), - onRemoveField: jest.fn(), - selectedIndexPattern: indexPattern, - setIndexPattern: jest.fn(), - state: {}, - }; -} - -describe('discover sidebar', function () { - let props: DiscoverSidebarProps; - let comp: ReactWrapper; - - beforeAll(() => { - props = getCompProps(); - comp = mountWithIntl(); - }); - - it('should have Selected Fields and Available Fields with Popular Fields sections', function () { - const popular = findTestSubject(comp, 'fieldList-popular'); - const selected = findTestSubject(comp, 'fieldList-selected'); - const unpopular = findTestSubject(comp, 'fieldList-unpopular'); - expect(popular.children().length).toBe(1); - expect(unpopular.children().length).toBe(7); - expect(selected.children().length).toBe(1); - }); - it('should allow selecting fields', function () { - findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); - expect(props.onAddField).toHaveBeenCalledWith('bytes'); - }); - it('should allow deselecting fields', function () { - findTestSubject(comp, 'fieldToggle-extension').simulate('click'); - expect(props.onRemoveField).toHaveBeenCalledWith('extension'); - }); - it('should allow adding filters', function () { - findTestSubject(comp, 'field-extension-showDetails').simulate('click'); - findTestSubject(comp, 'plus-extension-gif').simulate('click'); - expect(props.onAddFilter).toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.tsx deleted file mode 100644 index 865aff590286..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/discover_sidebar.tsx +++ /dev/null @@ -1,326 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 './discover_sidebar.scss'; -import React, { useCallback, useEffect, useState, useMemo } from 'react'; -import { i18n } from '@osd/i18n'; -import { EuiButtonIcon, EuiTitle, EuiSpacer } from '@elastic/eui'; -import { sortBy } from 'lodash'; -import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; -import { DiscoverField } from './discover_field'; -import { DiscoverIndexPattern } from './discover_index_pattern'; -import { DiscoverFieldSearch } from './discover_field_search'; -import { IndexPatternAttributes } from '../../../../../data/common'; -import { SavedObject } from '../../../../../../core/types'; -import { FIELDS_LIMIT_SETTING } from '../../../../common'; -import { groupFields } from './lib/group_fields'; -import { IndexPatternField, IndexPattern, UI_SETTINGS } from '../../../../../data/public'; -import { getDetails } from './lib/get_details'; -import { getDefaultFieldFilter, setFieldFilterProp } from './lib/field_filter'; -import { getIndexPatternFieldList } from './lib/get_index_pattern_field_list'; -import { getServices } from '../../../opensearch_dashboards_services'; - -export interface DiscoverSidebarProps { - /** - * the selected columns displayed in the doc table in discover - */ - columns: string[]; - /** - * a statistics of the distribution of fields in the given hits - */ - fieldCounts: Record; - /** - * hits fetched from OpenSearch, displayed in the doc table - */ - hits: Array>; - /** - * List of available index patterns - */ - indexPatternList: Array>; - /** - * Callback function when selecting a field - */ - onAddField: (fieldName: string) => void; - /** - * Callback function when adding a filter from sidebar - */ - onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; - /** - * Callback function when removing a field - * @param fieldName - */ - onRemoveField: (fieldName: string) => void; - /** - * Currently selected index pattern - */ - selectedIndexPattern?: IndexPattern; - /** - * Callback function to select another index pattern - */ - setIndexPattern: (id: string) => void; -} - -export function DiscoverSidebar({ - columns, - fieldCounts, - hits, - indexPatternList, - onAddField, - onAddFilter, - onRemoveField, - selectedIndexPattern, - setIndexPattern, -}: DiscoverSidebarProps) { - const [showFields, setShowFields] = useState(false); - const [fields, setFields] = useState(null); - const [fieldFilterState, setFieldFilterState] = useState(getDefaultFieldFilter()); - const services = useMemo(() => getServices(), []); - - useEffect(() => { - const newFields = getIndexPatternFieldList(selectedIndexPattern, fieldCounts); - setFields(newFields); - }, [selectedIndexPattern, fieldCounts, hits, services]); - - const onChangeFieldSearch = useCallback( - (field: string, value: string | boolean | undefined) => { - const newState = setFieldFilterProp(fieldFilterState, field, value); - setFieldFilterState(newState); - }, - [fieldFilterState] - ); - - const getDetailsByField = useCallback( - (ipField: IndexPatternField) => getDetails(ipField, hits, selectedIndexPattern), - [hits, selectedIndexPattern] - ); - - const popularLimit = services.uiSettings.get(FIELDS_LIMIT_SETTING); - const useShortDots = services.uiSettings.get(UI_SETTINGS.SHORT_DOTS_ENABLE); - - const { - selected: selectedFields, - popular: popularFields, - unpopular: unpopularFields, - } = useMemo(() => groupFields(fields, columns, popularLimit, fieldCounts, fieldFilterState), [ - fields, - columns, - popularLimit, - fieldCounts, - fieldFilterState, - ]); - - const fieldTypes = useMemo(() => { - const result = ['any']; - if (Array.isArray(fields)) { - for (const field of fields) { - if (result.indexOf(field.type) === -1) { - result.push(field.type); - } - } - } - return result; - }, [fields]); - - if (!selectedIndexPattern || !fields) { - return null; - } - - return ( - -
- o.attributes.title)} - /> -
-
- - -
-
- {fields.length > 0 && ( - <> - -

- -

-
- -
    - {selectedFields.map((field: IndexPatternField) => { - return ( -
  • - -
  • - ); - })} -
-
- -

- -

-
-
- setShowFields(!showFields)} - aria-label={ - showFields - ? i18n.translate( - 'discover.fieldChooser.filter.indexAndFieldsSectionHideAriaLabel', - { - defaultMessage: 'Hide fields', - } - ) - : i18n.translate( - 'discover.fieldChooser.filter.indexAndFieldsSectionShowAriaLabel', - { - defaultMessage: 'Show fields', - } - ) - } - /> -
-
- - )} - {popularFields.length > 0 && ( -
- - - -
    - {popularFields.map((field: IndexPatternField) => { - return ( -
  • - -
  • - ); - })} -
-
- )} - -
    - {unpopularFields.map((field: IndexPatternField) => { - return ( -
  • - -
  • - ); - })} -
-
-
-
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/index.ts b/src/plugins/discover_legacy/public/application/components/sidebar/index.ts deleted file mode 100644 index 2799d47da83f..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { DiscoverSidebar } from './discover_sidebar'; diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_calculator.test.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_calculator.test.ts deleted file mode 100644 index d580f7ae228a..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_calculator.test.ts +++ /dev/null @@ -1,268 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -// @ts-ignore -import realHits from 'fixtures/real_hits.js'; -// @ts-ignore -import stubbedLogstashFields from 'fixtures/logstash_fields'; -import { coreMock } from '../../../../../../../core/public/mocks'; -import { IndexPattern, IndexPatternField } from '../../../../../../data/public'; -import { getStubIndexPattern } from '../../../../../../data/public/test_utils'; -import { - groupValues, - getFieldValues, - getFieldValueCounts, - FieldValueCountsParams, -} from './field_calculator'; -import { Bucket } from '../types'; - -let indexPattern: IndexPattern; - -describe('field_calculator', function () { - beforeEach(function () { - indexPattern = getStubIndexPattern( - 'logstash-*', - (cfg: any) => cfg, - 'time', - stubbedLogstashFields(), - coreMock.createSetup() - ); - }); - - describe('groupValues', function () { - let groups: Record; - let grouped: boolean; - let values: any[]; - beforeEach(function () { - values = [ - ['foo', 'bar'], - 'foo', - 'foo', - undefined, - ['foo', 'bar'], - 'bar', - 'baz', - null, - null, - null, - 'foo', - undefined, - ]; - groups = groupValues(values, grouped); - }); - - it('should return an object values', function () { - expect(groups).toBeInstanceOf(Object); - }); - - it('should throw an error if any value is a plain object', function () { - expect(function () { - groupValues([{}, true, false], grouped); - }).toThrowError(); - }); - - it('should handle values with dots in them', function () { - values = ['0', '0.........', '0.......,.....']; - groups = groupValues(values, grouped); - expect(groups[values[0]].count).toBe(1); - expect(groups[values[1]].count).toBe(1); - expect(groups[values[2]].count).toBe(1); - }); - - it('should have a key for value in the array when not grouping array terms', function () { - expect(_.keys(groups).length).toBe(3); - expect(groups.foo).toBeInstanceOf(Object); - expect(groups.bar).toBeInstanceOf(Object); - expect(groups.baz).toBeInstanceOf(Object); - }); - - it('should count array terms independently', function () { - expect(groups['foo,bar']).toBeUndefined(); - expect(groups.foo.count).toBe(5); - expect(groups.bar.count).toBe(3); - expect(groups.baz.count).toBe(1); - }); - - describe('grouped array terms', function () { - beforeEach(function () { - grouped = true; - groups = groupValues(values, grouped); - }); - - it('should group array terms when grouped is true', function () { - expect(_.keys(groups).length).toBe(4); - expect(groups['foo,bar']).toBeInstanceOf(Object); - }); - - it('should contain the original array as the value', function () { - expect(groups['foo,bar'].value).toEqual(['foo', 'bar']); - }); - - it('should count the pairs separately from the values they contain', function () { - expect(groups['foo,bar'].count).toBe(2); - expect(groups.foo.count).toBe(3); - expect(groups.bar.count).toBe(1); - }); - }); - }); - - describe('getFieldValues', function () { - let hits: any; - - beforeEach(function () { - hits = _.each(_.cloneDeep(realHits), (hit) => indexPattern.flattenHit(hit)); - }); - - it('should return an array of values for _source fields', function () { - const extensions = getFieldValues({ - hits, - field: indexPattern.fields.getByName('extension') as IndexPatternField, - indexPattern, - }); - expect(extensions).toBeInstanceOf(Array); - expect( - _.filter(extensions, function (v) { - return v === 'html'; - }).length - ).toBe(8); - expect(_.uniq(_.clone(extensions)).sort()).toEqual(['gif', 'html', 'php', 'png']); - }); - - it('should return an array of values for core meta fields', function () { - const types = getFieldValues({ - hits, - field: indexPattern.fields.getByName('_type') as IndexPatternField, - indexPattern, - }); - expect(types).toBeInstanceOf(Array); - expect( - _.filter(types, function (v) { - return v === 'apache'; - }).length - ).toBe(18); - expect(_.uniq(_.clone(types)).sort()).toEqual(['apache', 'nginx']); - }); - }); - - describe('getFieldValueCounts', function () { - let params: FieldValueCountsParams; - beforeEach(function () { - params = { - hits: _.cloneDeep(realHits), - field: indexPattern.fields.getByName('extension') as IndexPatternField, - count: 3, - indexPattern, - }; - }); - - it('counts the top 5 values by default', function () { - params.hits = params.hits.map((hit: Record, i) => ({ - ...hit, - _source: { - extension: `${hit._source.extension}-${i}`, - }, - })); - params.count = undefined; - const extensions = getFieldValueCounts(params); - expect(extensions).toBeInstanceOf(Object); - expect(extensions.buckets).toBeInstanceOf(Array); - const buckets = extensions.buckets as Bucket[]; - expect(buckets.length).toBe(5); - expect(extensions.error).toBeUndefined(); - }); - - it('counts only distinct values if less than default', function () { - params.count = undefined; - const extensions = getFieldValueCounts(params); - expect(extensions).toBeInstanceOf(Object); - expect(extensions.buckets).toBeInstanceOf(Array); - const buckets = extensions.buckets as Bucket[]; - expect(buckets.length).toBe(4); - expect(extensions.error).toBeUndefined(); - }); - - it('counts only distinct values if less than specified count', function () { - params.count = 10; - const extensions = getFieldValueCounts(params); - expect(extensions).toBeInstanceOf(Object); - expect(extensions.buckets).toBeInstanceOf(Array); - const buckets = extensions.buckets as Bucket[]; - expect(buckets.length).toBe(4); - expect(extensions.error).toBeUndefined(); - }); - - it('counts the top 3 values', function () { - const extensions = getFieldValueCounts(params); - expect(extensions).toBeInstanceOf(Object); - expect(extensions.buckets).toBeInstanceOf(Array); - const buckets = extensions.buckets as Bucket[]; - expect(buckets.length).toBe(3); - expect(_.map(buckets, 'value')).toEqual(['html', 'gif', 'php']); - expect(extensions.error).toBeUndefined(); - }); - - it('fails to analyze geo and attachment types', function () { - params.field = indexPattern.fields.getByName('point') as IndexPatternField; - expect(getFieldValueCounts(params).error).not.toBeUndefined(); - - params.field = indexPattern.fields.getByName('area') as IndexPatternField; - expect(getFieldValueCounts(params).error).not.toBeUndefined(); - - params.field = indexPattern.fields.getByName('request_body') as IndexPatternField; - expect(getFieldValueCounts(params).error).not.toBeUndefined(); - }); - - it('fails to analyze fields that are in the mapping, but not the hits', function () { - params.field = indexPattern.fields.getByName('ip') as IndexPatternField; - expect(getFieldValueCounts(params).error).not.toBeUndefined(); - }); - - it('counts the total hits', function () { - expect(getFieldValueCounts(params).total).toBe(params.hits.length); - }); - - it('counts the hits the field exists in', function () { - params.field = indexPattern.fields.getByName('phpmemory') as IndexPatternField; - expect(getFieldValueCounts(params).exists).toBe(5); - }); - - it('catches and returns errors', function () { - params.hits = params.hits.map((hit: Record) => ({ - ...hit, - _source: { - extension: { foo: hit._source.extension }, - }, - })); - params.grouped = true; - expect(typeof getFieldValueCounts(params).error).toBe('string'); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_calculator.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_calculator.ts deleted file mode 100644 index 54f8832fa1fc..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_calculator.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; -import { IndexPattern, IndexPatternField } from 'src/plugins/data/public'; -import { FieldValueCounts } from '../types'; - -const NO_ANALYSIS_TYPES = ['geo_point', 'geo_shape', 'attachment']; - -interface FieldValuesParams { - hits: Array>; - field: IndexPatternField; - indexPattern: IndexPattern; -} - -interface FieldValueCountsParams extends FieldValuesParams { - count?: number; - grouped?: boolean; -} - -const getFieldValues = ({ hits, field, indexPattern }: FieldValuesParams) => { - const name = field.name; - const flattenHit = indexPattern.flattenHit; - return hits.map((hit) => flattenHit(hit)[name]); -}; - -const getFieldValueCounts = (params: FieldValueCountsParams): FieldValueCounts => { - const { hits, field, indexPattern, count = 5, grouped = false } = params; - const { type: fieldType } = field; - - if (NO_ANALYSIS_TYPES.includes(fieldType)) { - return { - error: i18n.translate( - 'discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForGeoFieldsErrorMessage', - { - defaultMessage: 'Analysis is not available for {fieldType} fields.', - values: { - fieldType, - }, - } - ), - }; - } - - const allValues = getFieldValues({ hits, field, indexPattern }); - const missing = allValues.filter((v) => v === undefined || v === null).length; - - try { - const groups = groupValues(allValues, grouped); - const counts = Object.keys(groups) - .sort((a, b) => groups[b].count - groups[a].count) - .slice(0, count) - .map((key) => ({ - value: groups[key].value, - count: groups[key].count, - percent: (groups[key].count / (hits.length - missing)) * 100, - display: indexPattern.getFormatterForField(field).convert(groups[key].value), - })); - - if (hits.length === missing) { - return { - error: i18n.translate( - 'discover.fieldChooser.fieldCalculator.fieldIsNotPresentInDocumentsErrorMessage', - { - defaultMessage: - 'This field is present in your OpenSearch mapping but not in the {hitsLength} documents shown in the doc table. You may still be able to visualize or search on it.', - values: { - hitsLength: hits.length, - }, - } - ), - }; - } - - return { - total: hits.length, - exists: hits.length - missing, - missing, - buckets: counts, - }; - } catch (e) { - return { - error: e instanceof Error ? e.message : String(e), - }; - } -}; - -const groupValues = ( - allValues: any[], - grouped?: boolean -): Record => { - const values = grouped ? allValues : allValues.flat(); - - return values - .filter((v) => { - if (v instanceof Object && !Array.isArray(v)) { - throw new Error( - i18n.translate( - 'discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForObjectFieldsErrorMessage', - { - defaultMessage: 'Analysis is not available for object fields.', - } - ) - ); - } - return v !== undefined && v !== null; - }) - .reduce((groups, value) => { - if (groups.hasOwnProperty(value)) { - groups[value].count++; - } else { - groups[value] = { - value, - count: 1, - }; - } - return groups; - }, {}); -}; - -export { FieldValueCountsParams, groupValues, getFieldValues, getFieldValueCounts }; diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_filter.test.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_filter.test.ts deleted file mode 100644 index a21d93cb5bc4..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_filter.test.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getDefaultFieldFilter, setFieldFilterProp, isFieldFiltered } from './field_filter'; -import { IndexPatternField } from '../../../../../../data/public'; - -describe('field_filter', function () { - it('getDefaultFieldFilter should return default filter state', function () { - expect(getDefaultFieldFilter()).toMatchInlineSnapshot(` - Object { - "aggregatable": null, - "missing": true, - "name": "", - "searchable": null, - "type": "any", - } - `); - }); - it('setFieldFilterProp should return allow filter changes', function () { - const state = getDefaultFieldFilter(); - const targetState = { - aggregatable: true, - missing: true, - name: 'test', - searchable: true, - type: 'string', - }; - const actualState = Object.entries(targetState).reduce((acc, kv) => { - return setFieldFilterProp(acc, kv[0], kv[1]); - }, state); - expect(actualState).toMatchInlineSnapshot(` - Object { - "aggregatable": true, - "missing": true, - "name": "test", - "searchable": true, - "type": "string", - } - `); - }); - it('filters a given list', () => { - const defaultState = getDefaultFieldFilter(); - const fieldList = [ - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: false, - aggregatable: false, - }, - { - name: 'extension', - type: 'string', - esTypes: ['text'], - count: 10, - scripted: true, - searchable: true, - aggregatable: true, - }, - ] as IndexPatternField[]; - - [ - { filter: {}, result: ['bytes', 'extension'] }, - { filter: { name: 'by' }, result: ['bytes'] }, - { filter: { aggregatable: true }, result: ['extension'] }, - { filter: { aggregatable: true, searchable: false }, result: [] }, - { filter: { type: 'string' }, result: ['extension'] }, - ].forEach((test) => { - const filtered = fieldList - .filter((field) => - isFieldFiltered(field, { ...defaultState, ...test.filter }, { bytes: 1, extension: 1 }) - ) - .map((field) => field.name); - - expect(filtered).toEqual(test.result); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_filter.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_filter.ts deleted file mode 100644 index d72af29b43e0..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/field_filter.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 '../../../../../../data/public'; - -export interface FieldFilterState { - missing: boolean; - type: string; - name: string; - aggregatable: null | boolean; - searchable: null | boolean; -} - -export function getDefaultFieldFilter(): FieldFilterState { - return { - missing: true, - type: 'any', - name: '', - aggregatable: null, - searchable: null, - }; -} - -export function setFieldFilterProp( - state: FieldFilterState, - name: string, - value: string | boolean | null | undefined -): FieldFilterState { - const newState = { ...state }; - if (name === 'missing') { - newState.missing = Boolean(value); - } else if (name === 'aggregatable') { - newState.aggregatable = typeof value !== 'boolean' ? null : value; - } else if (name === 'searchable') { - newState.searchable = typeof value !== 'boolean' ? null : value; - } else if (name === 'name') { - newState.name = String(value); - } else if (name === 'type') { - newState.type = String(value); - } - return newState; -} - -export function isFieldFiltered( - field: IndexPatternField, - filterState: FieldFilterState, - fieldCounts: Record -): boolean { - const matchFilter = filterState.type === 'any' || field.type === filterState.type; - const isAggregatable = - filterState.aggregatable === null || field.aggregatable === filterState.aggregatable; - const isSearchable = - filterState.searchable === null || field.searchable === filterState.searchable; - const scriptedOrMissing = - !filterState.missing || - field.type === '_source' || - field.scripted || - fieldCounts[field.name] > 0; - const matchName = !filterState.name || field.name.indexOf(filterState.name) !== -1; - - return matchFilter && isAggregatable && isSearchable && scriptedOrMissing && matchName; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_details.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_details.ts deleted file mode 100644 index 823cbde9ba72..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_details.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -// @ts-ignore -import { i18n } from '@osd/i18n'; -import { getFieldValueCounts } from './field_calculator'; -import { IndexPattern, IndexPatternField } from '../../../../../../data/public'; - -export function getDetails( - field: IndexPatternField, - hits: Array>, - indexPattern?: IndexPattern -) { - const defaultDetails = { - error: '', - exists: 0, - total: 0, - buckets: [], - }; - if (!indexPattern) { - return { - ...defaultDetails, - error: i18n.translate('discover.fieldChooser.noIndexPatternSelectedErrorMessage', { - defaultMessage: 'Index pattern not specified.', - }), - }; - } - const details = { - ...defaultDetails, - ...getFieldValueCounts({ - hits, - field, - indexPattern, - count: 5, - grouped: false, - }), - }; - if (details.buckets) { - for (const bucket of details.buckets) { - bucket.display = indexPattern.getFormatterForField(field).convert(bucket.value); - } - } - return details; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_field_type_name.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_field_type_name.ts deleted file mode 100644 index 38b18792d3e4..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_field_type_name.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; - -export function getFieldTypeName(type: string) { - switch (type) { - case 'boolean': - return i18n.translate('discover.fieldNameIcons.booleanAriaLabel', { - defaultMessage: 'Boolean field', - }); - case 'conflict': - return i18n.translate('discover.fieldNameIcons.conflictFieldAriaLabel', { - defaultMessage: 'Conflicting field', - }); - case 'date': - return i18n.translate('discover.fieldNameIcons.dateFieldAriaLabel', { - defaultMessage: 'Date field', - }); - case 'geo_point': - return i18n.translate('discover.fieldNameIcons.geoPointFieldAriaLabel', { - defaultMessage: 'Geo point field', - }); - case 'geo_shape': - return i18n.translate('discover.fieldNameIcons.geoShapeFieldAriaLabel', { - defaultMessage: 'Geo shape field', - }); - case 'ip': - return i18n.translate('discover.fieldNameIcons.ipAddressFieldAriaLabel', { - defaultMessage: 'IP address field', - }); - case 'murmur3': - return i18n.translate('discover.fieldNameIcons.murmur3FieldAriaLabel', { - defaultMessage: 'Murmur3 field', - }); - case 'number': - return i18n.translate('discover.fieldNameIcons.numberFieldAriaLabel', { - defaultMessage: 'Number field', - }); - case 'source': - // Note that this type is currently not provided, type for _source is undefined - return i18n.translate('discover.fieldNameIcons.sourceFieldAriaLabel', { - defaultMessage: 'Source field', - }); - case 'string': - return i18n.translate('discover.fieldNameIcons.stringFieldAriaLabel', { - defaultMessage: 'String field', - }); - case 'nested': - return i18n.translate('discover.fieldNameIcons.nestedFieldAriaLabel', { - defaultMessage: 'Nested field', - }); - default: - return i18n.translate('discover.fieldNameIcons.unknownFieldAriaLabel', { - defaultMessage: 'Unknown field', - }); - } -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_index_pattern_field_list.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_index_pattern_field_list.ts deleted file mode 100644 index b3a8ff5cd8d9..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_index_pattern_field_list.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { difference } from 'lodash'; -import { IndexPattern, IndexPatternField } from 'src/plugins/data/public'; - -export function getIndexPatternFieldList( - indexPattern?: IndexPattern, - fieldCounts?: Record -) { - if (!indexPattern || !fieldCounts) return []; - - const fieldNamesInDocs = Object.keys(fieldCounts); - const fieldNamesInIndexPattern = indexPattern.fields.getAll().map((fld) => fld.name); - const unknownTypes: IndexPatternField[] = []; - - difference(fieldNamesInDocs, fieldNamesInIndexPattern).forEach((unknownFieldName) => { - unknownTypes.push({ - displayName: String(unknownFieldName), - name: String(unknownFieldName), - type: 'unknown', - } as IndexPatternField); - }); - - return [...indexPattern.fields.getAll(), ...unknownTypes]; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_warnings.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_warnings.ts deleted file mode 100644 index 770a0ce664e4..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/get_warnings.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; -import { IndexPatternField } from '../../../../../../data/public'; - -export function getWarnings(field: IndexPatternField) { - let warnings = []; - - if (field.scripted) { - warnings.push( - i18n.translate( - 'discover.fieldChooser.discoverField.scriptedFieldsTakeLongExecuteDescription', - { - defaultMessage: 'Scripted fields can take a long time to execute.', - } - ) - ); - } - - if (warnings.length > 1) { - warnings = warnings.map(function (warning, i) { - return (i > 0 ? '\n' : '') + (i + 1) + ' - ' + warning; - }); - } - - return warnings; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/group_fields.test.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/group_fields.test.ts deleted file mode 100644 index 7301ce3a4c96..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/group_fields.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { groupFields } from './group_fields'; -import { getDefaultFieldFilter } from './field_filter'; - -describe('group_fields', function () { - it('should group fields in selected, popular, unpopular group', function () { - const fields = [ - { - name: 'category', - type: 'string', - esTypes: ['text'], - count: 1, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'currency', - type: 'string', - esTypes: ['keyword'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'customer_birth_date', - type: 'date', - esTypes: ['date'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - ]; - - const fieldCounts = { - category: 1, - currency: 1, - customer_birth_date: 1, - }; - - const fieldFilterState = getDefaultFieldFilter(); - - const actual = groupFields(fields as any, ['currency'], 5, fieldCounts, fieldFilterState); - expect(actual).toMatchInlineSnapshot(` - Object { - "popular": Array [ - Object { - "aggregatable": true, - "count": 1, - "esTypes": Array [ - "text", - ], - "name": "category", - "readFromDocValues": true, - "scripted": false, - "searchable": true, - "type": "string", - }, - ], - "selected": Array [ - Object { - "aggregatable": true, - "count": 0, - "esTypes": Array [ - "keyword", - ], - "name": "currency", - "readFromDocValues": true, - "scripted": false, - "searchable": true, - "type": "string", - }, - ], - "unpopular": Array [ - Object { - "aggregatable": true, - "count": 0, - "esTypes": Array [ - "date", - ], - "name": "customer_birth_date", - "readFromDocValues": true, - "scripted": false, - "searchable": true, - "type": "date", - }, - ], - } - `); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/group_fields.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/lib/group_fields.tsx deleted file mode 100644 index fad1db402467..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/group_fields.tsx +++ /dev/null @@ -1,87 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 'src/plugins/data/public'; -import { FieldFilterState, isFieldFiltered } from './field_filter'; - -interface GroupedFields { - selected: IndexPatternField[]; - popular: IndexPatternField[]; - unpopular: IndexPatternField[]; -} - -/** - * group the fields into selected, popular and unpopular, filter by fieldFilterState - */ -export function groupFields( - fields: IndexPatternField[] | null, - columns: string[], - popularLimit: number, - fieldCounts: Record, - fieldFilterState: FieldFilterState -): GroupedFields { - const result: GroupedFields = { - selected: [], - popular: [], - unpopular: [], - }; - if (!Array.isArray(fields) || !Array.isArray(columns) || typeof fieldCounts !== 'object') { - return result; - } - - const popular = fields - .filter((field) => !columns.includes(field.name) && field.count) - .sort((a: IndexPatternField, b: IndexPatternField) => (b.count || 0) - (a.count || 0)) - .map((field) => field.name) - .slice(0, popularLimit); - - const compareFn = (a: IndexPatternField, b: IndexPatternField) => { - if (!a.displayName) { - return 0; - } - return a.displayName.localeCompare(b.displayName || ''); - }; - const fieldsSorted = fields.sort(compareFn); - - for (const field of fieldsSorted) { - if (!isFieldFiltered(field, fieldFilterState, fieldCounts)) { - continue; - } - if (columns.includes(field.name)) { - result.selected.push(field); - } else if (popular.includes(field.name) && field.type !== '_source') { - result.popular.push(field); - } else if (field.type !== '_source') { - result.unpopular.push(field); - } - } - - return result; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/lib/visualize_trigger_utils.ts b/src/plugins/discover_legacy/public/application/components/sidebar/lib/visualize_trigger_utils.ts deleted file mode 100644 index 36a6bcf2e329..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/lib/visualize_trigger_utils.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { - VISUALIZE_FIELD_TRIGGER, - VISUALIZE_GEO_FIELD_TRIGGER, - visualizeFieldTrigger, - visualizeGeoFieldTrigger, -} from '../../../../../../ui_actions/public'; -import { getUiActions } from '../../../../opensearch_dashboards_services'; -import { IndexPatternField, OSD_FIELD_TYPES } from '../../../../../../data/public'; - -function getTriggerConstant(type: string) { - return type === OSD_FIELD_TYPES.GEO_POINT || type === OSD_FIELD_TYPES.GEO_SHAPE - ? VISUALIZE_GEO_FIELD_TRIGGER - : VISUALIZE_FIELD_TRIGGER; -} - -function getTrigger(type: string) { - return type === OSD_FIELD_TYPES.GEO_POINT || type === OSD_FIELD_TYPES.GEO_SHAPE - ? visualizeGeoFieldTrigger - : visualizeFieldTrigger; -} - -async function getCompatibleActions( - fieldName: string, - indexPatternId: string, - contextualFields: string[], - trigger: typeof VISUALIZE_FIELD_TRIGGER | typeof VISUALIZE_GEO_FIELD_TRIGGER -) { - const compatibleActions = await getUiActions().getTriggerCompatibleActions(trigger, { - indexPatternId, - fieldName, - contextualFields, - }); - return compatibleActions; -} - -export async function getVisualizeHref( - field: IndexPatternField, - indexPatternId: string | undefined, - contextualFields: string[] -) { - if (!indexPatternId) return undefined; - const triggerOptions = { - indexPatternId, - fieldName: field.name, - contextualFields, - trigger: getTrigger(field.type), - }; - const compatibleActions = await getCompatibleActions( - field.name, - indexPatternId, - contextualFields, - getTriggerConstant(field.type) - ); - // enable the link only if only one action is registered - return compatibleActions.length === 1 - ? compatibleActions[0].getHref?.(triggerOptions) - : undefined; -} - -export function triggerVisualizeActions( - field: IndexPatternField, - indexPatternId: string | undefined, - contextualFields: string[] -) { - if (!indexPatternId) return; - const trigger = getTriggerConstant(field.type); - const triggerOptions = { - indexPatternId, - fieldName: field.name, - contextualFields, - }; - getUiActions().getTrigger(trigger).exec(triggerOptions); -} - -export async function isFieldVisualizable( - field: IndexPatternField, - indexPatternId: string | undefined, - contextualFields: string[] -) { - if (field.name === '_id' || !indexPatternId) { - // for first condition you'd get a 'Fielddata access on the _id field is disallowed' error on OpenSearch side. - return false; - } - const trigger = getTriggerConstant(field.type); - const compatibleActions = await getCompatibleActions( - field.name, - indexPatternId, - contextualFields, - trigger - ); - return compatibleActions.length > 0 && field.visualizable; -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/string_progress_bar.tsx b/src/plugins/discover_legacy/public/application/components/sidebar/string_progress_bar.tsx deleted file mode 100644 index dba087d0f9ed..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/string_progress_bar.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiProgress } from '@elastic/eui'; - -interface Props { - percent: number; - count: number; - value: string; -} - -export function StringFieldProgressBar({ value, percent, count }: Props) { - const ariaLabel = `${value}: ${count} (${percent}%)`; - - return ( - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/sidebar/types.ts b/src/plugins/discover_legacy/public/application/components/sidebar/types.ts deleted file mode 100644 index a43120b28e96..000000000000 --- a/src/plugins/discover_legacy/public/application/components/sidebar/types.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 interface IndexPatternRef { - id: string; - title: string; -} - -export interface FieldDetails { - error: string; - exists: number; - total: number; - buckets: Bucket[]; -} - -export interface FieldValueCounts extends Partial { - missing?: number; -} - -export interface Bucket { - display: string; - value: string; - percent: number; - count: number; -} diff --git a/src/plugins/discover_legacy/public/application/components/skip_bottom_button/index.ts b/src/plugins/discover_legacy/public/application/components/skip_bottom_button/index.ts deleted file mode 100644 index 094d8e286875..000000000000 --- a/src/plugins/discover_legacy/public/application/components/skip_bottom_button/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { SkipBottomButton } from './skip_bottom_button'; diff --git a/src/plugins/discover_legacy/public/application/components/skip_bottom_button/skip_bottom_button.test.tsx b/src/plugins/discover_legacy/public/application/components/skip_bottom_button/skip_bottom_button.test.tsx deleted file mode 100644 index 28ffef9dae86..000000000000 --- a/src/plugins/discover_legacy/public/application/components/skip_bottom_button/skip_bottom_button.test.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ReactWrapper } from 'enzyme'; -import { SkipBottomButton, SkipBottomButtonProps } from './skip_bottom_button'; - -describe('Skip to Bottom Button', function () { - let props: SkipBottomButtonProps; - let component: ReactWrapper; - - beforeAll(() => { - props = { - onClick: jest.fn(), - }; - }); - - it('should be clickable', function () { - component = mountWithIntl(); - component.simulate('click'); - expect(props.onClick).toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/skip_bottom_button/skip_bottom_button.tsx b/src/plugins/discover_legacy/public/application/components/skip_bottom_button/skip_bottom_button.tsx deleted file mode 100644 index a1e5754cb312..000000000000 --- a/src/plugins/discover_legacy/public/application/components/skip_bottom_button/skip_bottom_button.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiSkipLink } from '@elastic/eui'; -import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; - -export interface SkipBottomButtonProps { - /** - * Action to perform on click - */ - onClick: () => void; -} - -export function SkipBottomButton({ onClick }: SkipBottomButtonProps) { - return ( - - { - // prevent the anchor to reload the page on click - event.preventDefault(); - // The destinationId prop cannot be leveraged here as the table needs - // to be updated first (angular logic) - onClick(); - }} - className="dscSkipButton" - destinationId="" - data-test-subj="discoverSkipTableButton" - > - - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table.test.tsx b/src/plugins/discover_legacy/public/application/components/table/table.test.tsx deleted file mode 100644 index 220ac57feae2..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table.test.tsx +++ /dev/null @@ -1,279 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mount } from 'enzyme'; -import { findTestSubject } from 'test_utils/helpers'; -import { DocViewTable } from './table'; -import { indexPatterns, IndexPattern } from '../../../../../data/public'; - -const indexPattern = ({ - fields: { - getAll: () => [ - { - name: '_index', - type: 'string', - scripted: false, - filterable: true, - }, - { - name: 'message', - type: 'string', - scripted: false, - filterable: false, - }, - { - name: 'extension', - type: 'string', - scripted: false, - filterable: true, - }, - { - name: 'bytes', - type: 'number', - scripted: false, - filterable: true, - }, - { - name: 'scripted', - type: 'number', - scripted: true, - filterable: false, - }, - ], - }, - metaFields: ['_index', '_score'], - flattenHit: undefined, - formatHit: jest.fn((hit) => hit._source), -} as unknown) as IndexPattern; - -indexPattern.fields.getByName = (name: string) => { - return indexPattern.fields.getAll().find((field) => field.name === name); -}; - -indexPattern.flattenHit = indexPatterns.flattenHitWrapper(indexPattern, indexPattern.metaFields); - -describe('DocViewTable at Discover', () => { - // At Discover's main view, all buttons are rendered - // check for existence of action buttons and warnings - - const hit = { - _index: 'logstash-2014.09.09', - _type: 'doc', - _id: 'id123', - _score: 1, - _source: { - message: - 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. \ - Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus \ - et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, \ - ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. \ - Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, \ - rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. \ - Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. \ - Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut', - extension: 'html', - not_mapped: 'yes', - bytes: 100, - objectArray: [{ foo: true }], - relatedContent: { - test: 1, - }, - scripted: 123, - _underscore: 123, - }, - }; - - const props = { - hit, - columns: ['extension'], - indexPattern, - filter: jest.fn(), - onAddColumn: jest.fn(), - onRemoveColumn: jest.fn(), - }; - const component = mount(); - [ - { - _property: '_index', - addInclusiveFilterButton: true, - collapseBtn: false, - noMappingWarning: false, - toggleColumnButton: true, - underscoreWarning: false, - }, - { - _property: 'message', - addInclusiveFilterButton: false, - collapseBtn: true, - noMappingWarning: false, - toggleColumnButton: true, - underscoreWarning: false, - }, - { - _property: '_underscore', - addInclusiveFilterButton: false, - collapseBtn: false, - noMappingWarning: false, - toggleColumnButton: true, - underScoreWarning: true, - }, - { - _property: 'scripted', - addInclusiveFilterButton: false, - collapseBtn: false, - noMappingWarning: false, - toggleColumnButton: true, - underScoreWarning: false, - }, - { - _property: 'not_mapped', - addInclusiveFilterButton: false, - collapseBtn: false, - noMappingWarning: true, - toggleColumnButton: true, - underScoreWarning: false, - }, - ].forEach((check) => { - const rowComponent = findTestSubject(component, `tableDocViewRow-${check._property}`); - - it(`renders row for ${check._property}`, () => { - expect(rowComponent.length).toBe(1); - }); - - ([ - 'addInclusiveFilterButton', - 'collapseBtn', - 'toggleColumnButton', - 'underscoreWarning', - ] as const).forEach((element) => { - const elementExist = check[element]; - - if (typeof elementExist === 'boolean') { - const btn = findTestSubject(rowComponent, element); - - it(`renders ${element} for '${check._property}' correctly`, () => { - const disabled = btn.length ? btn.props().disabled : true; - const clickAble = btn.length && !disabled ? true : false; - expect(clickAble).toBe(elementExist); - }); - } - }); - - (['noMappingWarning'] as const).forEach((element) => { - const elementExist = check[element]; - - if (typeof elementExist === 'boolean') { - const el = findTestSubject(rowComponent, element); - - it(`renders ${element} for '${check._property}' correctly`, () => { - expect(el.length).toBe(elementExist ? 1 : 0); - }); - } - }); - }); -}); - -describe('DocViewTable at Discover Doc', () => { - const hit = { - _index: 'logstash-2014.09.09', - _score: 1, - _type: 'doc', - _id: 'id123', - _source: { - extension: 'html', - not_mapped: 'yes', - }, - }; - // here no action buttons are rendered - const props = { - hit, - indexPattern, - }; - const component = mount(); - const foundLength = findTestSubject(component, 'addInclusiveFilterButton').length; - - it(`renders no action buttons`, () => { - expect(foundLength).toBe(0); - }); -}); - -describe('DocViewTable at Discover Context', () => { - // here no toggleColumnButtons are rendered - const hit = { - _index: 'logstash-2014.09.09', - _type: 'doc', - _id: 'id123', - _score: 1, - _source: { - message: - 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. \ - Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus \ - et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, \ - ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. \ - Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, \ - rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. \ - Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. \ - Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut', - }, - }; - const props = { - hit, - columns: ['extension'], - indexPattern, - filter: jest.fn(), - }; - - const component = mount(); - - it(`renders no toggleColumnButton`, () => { - const foundLength = findTestSubject(component, 'toggleColumnButtons').length; - expect(foundLength).toBe(0); - }); - - it(`renders addInclusiveFilterButton`, () => { - const row = findTestSubject(component, `tableDocViewRow-_index`); - const btn = findTestSubject(row, 'addInclusiveFilterButton'); - expect(btn.length).toBe(1); - btn.simulate('click'); - expect(props.filter).toBeCalled(); - }); - - it(`renders functional collapse button`, () => { - const btn = findTestSubject(component, `collapseBtn`); - const html = component.html(); - - expect(component.html()).toContain('truncate-by-height'); - - expect(btn.length).toBe(1); - btn.simulate('click'); - expect(component.html() !== html).toBeTruthy(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/table/table.tsx b/src/plugins/discover_legacy/public/application/components/table/table.tsx deleted file mode 100644 index 90167a515985..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table.tsx +++ /dev/null @@ -1,149 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { useState } from 'react'; -import { escapeRegExp } from 'lodash'; -import { DocViewTableRow } from './table_row'; -import { arrayContainsObjects, trimAngularSpan } from './table_helper'; -import { DocViewRenderProps } from '../../doc_views/doc_views_types'; - -const COLLAPSE_LINE_LENGTH = 350; - -export function DocViewTable({ - hit, - indexPattern, - filter, - columns, - onAddColumn, - onRemoveColumn, -}: DocViewRenderProps) { - const mapping = indexPattern.fields.getByName; - const flattened = indexPattern.flattenHit(hit); - const formatted = indexPattern.formatHit(hit, 'html'); - const [fieldRowOpen, setFieldRowOpen] = useState({} as Record); - - function toggleValueCollapse(field: string) { - fieldRowOpen[field] = fieldRowOpen[field] !== true; - setFieldRowOpen({ ...fieldRowOpen }); - } - - return ( - - - {Object.keys(flattened) - .sort() - .map((field) => { - const valueRaw = flattened[field]; - const value = trimAngularSpan(String(formatted[field])); - - const isCollapsible = value.length > COLLAPSE_LINE_LENGTH; - const isCollapsed = isCollapsible && !fieldRowOpen[field]; - const toggleColumn = - onRemoveColumn && onAddColumn && Array.isArray(columns) - ? () => { - if (columns.includes(field)) { - onRemoveColumn(field); - } else { - onAddColumn(field); - } - } - : undefined; - const isArrayOfObjects = - Array.isArray(flattened[field]) && arrayContainsObjects(flattened[field]); - const displayUnderscoreWarning = !mapping(field) && field.indexOf('_') === 0; - const displayNoMappingWarning = - !mapping(field) && !displayUnderscoreWarning && !isArrayOfObjects; - - // Discover doesn't flatten arrays of objects, so for documents with an `object` or `nested` field that - // contains an array, Discover will only detect the top level root field. We want to detect when those - // root fields are `nested` so that we can display the proper icon and label. However, those root - // `nested` fields are not a part of the index pattern. Their children are though, and contain nested path - // info. So to detect nested fields we look through the index pattern for nested children - // whose path begins with the current field. There are edge cases where - // this could incorrectly identify a plain `object` field as `nested`. Say we had the following document - // where `foo` is a plain object field and `bar` is a nested field. - // { - // "foo": [ - // { - // "bar": [ - // { - // "baz": "qux" - // } - // ] - // }, - // { - // "bar": [ - // { - // "baz": "qux" - // } - // ] - // } - // ] - // } - // - // The following code will search for `foo`, find it at the beginning of the path to the nested child field - // `foo.bar.baz` and incorrectly mark `foo` as nested. Any time we're searching for the name of a plain object - // field that happens to match a segment of a nested path, we'll get a false positive. - // We're aware of this issue and we'll have to live with - // it in the short term. The long term fix will be to add info about the `nested` and `object` root fields - // to the index pattern, but that has its own complications which you can read more about in the following - // issue: https://github.com/elastic/kibana/issues/54957 - const isNestedField = - !indexPattern.fields.getByName(field) && - !!indexPattern.fields.getAll().find((patternField) => { - // We only want to match a full path segment - const nestedRootRegex = new RegExp(escapeRegExp(field) + '(\\.|$)'); - return nestedRootRegex.test(patternField.subType?.nested?.path ?? ''); - }); - const fieldType = isNestedField ? 'nested' : indexPattern.fields.getByName(field)?.type; - - return ( - toggleValueCollapse(field)} - onToggleColumn={toggleColumn} - value={value} - valueRaw={valueRaw} - /> - ); - })} - -
- ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_helper.test.ts b/src/plugins/discover_legacy/public/application/components/table/table_helper.test.ts deleted file mode 100644 index 20c1092ef86d..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_helper.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { arrayContainsObjects } from './table_helper'; - -describe('arrayContainsObjects', () => { - it(`returns false for an array of primitives`, () => { - const actual = arrayContainsObjects(['test', 'test']); - expect(actual).toBeFalsy(); - }); - - it(`returns true for an array of objects`, () => { - const actual = arrayContainsObjects([{}, {}]); - expect(actual).toBeTruthy(); - }); - - it(`returns true for an array of objects and primitves`, () => { - const actual = arrayContainsObjects([{}, 'sdf']); - expect(actual).toBeTruthy(); - }); - - it(`returns false for an array of null values`, () => { - const actual = arrayContainsObjects([null, null]); - expect(actual).toBeFalsy(); - }); - - it(`returns false if no array is given`, () => { - const actual = arrayContainsObjects([null, null]); - expect(actual).toBeFalsy(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/table/table_helper.tsx b/src/plugins/discover_legacy/public/application/components/table/table_helper.tsx deleted file mode 100644 index 2e63b43b8310..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_helper.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -/** - * Returns true if the given array contains at least 1 object - */ -export function arrayContainsObjects(value: unknown[]): boolean { - return Array.isArray(value) && value.some((v) => typeof v === 'object' && v !== null); -} - -/** - * Removes markup added by OpenSearch Dashboards fields html formatter - */ -export function trimAngularSpan(text: string): string { - return text.replace(/^/, '').replace(/<\/span>$/, ''); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_row.tsx b/src/plugins/discover_legacy/public/application/components/table/table_row.tsx deleted file mode 100644 index 95ba38106e3e..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_row.tsx +++ /dev/null @@ -1,129 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 classNames from 'classnames'; -import React, { ReactNode } from 'react'; -import { FieldMapping, DocViewFilterFn } from '../../doc_views/doc_views_types'; -import { DocViewTableRowBtnFilterAdd } from './table_row_btn_filter_add'; -import { DocViewTableRowBtnFilterRemove } from './table_row_btn_filter_remove'; -import { DocViewTableRowBtnToggleColumn } from './table_row_btn_toggle_column'; -import { DocViewTableRowBtnCollapse } from './table_row_btn_collapse'; -import { DocViewTableRowBtnFilterExists } from './table_row_btn_filter_exists'; -import { DocViewTableRowIconNoMapping } from './table_row_icon_no_mapping'; -import { DocViewTableRowIconUnderscore } from './table_row_icon_underscore'; -import { FieldName } from '../field_name/field_name'; - -export interface Props { - field: string; - fieldMapping?: FieldMapping; - fieldType: string; - displayNoMappingWarning: boolean; - displayUnderscoreWarning: boolean; - isCollapsible: boolean; - isColumnActive: boolean; - isCollapsed: boolean; - onToggleCollapse: () => void; - onFilter?: DocViewFilterFn; - onToggleColumn?: () => void; - value: string | ReactNode; - valueRaw: unknown; -} - -export function DocViewTableRow({ - field, - fieldMapping, - fieldType, - displayNoMappingWarning, - displayUnderscoreWarning, - isCollapsible, - isCollapsed, - isColumnActive, - onFilter, - onToggleCollapse, - onToggleColumn, - value, - valueRaw, -}: Props) { - const valueClassName = classNames({ - // eslint-disable-next-line @typescript-eslint/naming-convention - osdDocViewer__value: true, - 'truncate-by-height': isCollapsible && isCollapsed, - }); - - return ( - - {typeof onFilter === 'function' && ( - - onFilter(fieldMapping, valueRaw, '+')} - /> - onFilter(fieldMapping, valueRaw, '-')} - /> - {typeof onToggleColumn === 'function' && ( - - )} - onFilter('_exists_', field, '+')} - scripted={fieldMapping && fieldMapping.scripted} - /> - - )} - - - - - {isCollapsible && ( - - )} - {displayUnderscoreWarning && } - {displayNoMappingWarning && } -
- - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_collapse.tsx b/src/plugins/discover_legacy/public/application/components/table/table_row_btn_collapse.tsx deleted file mode 100644 index de25c73e9c95..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_collapse.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; -import { EuiToolTip, EuiButtonIcon } from '@elastic/eui'; - -export interface Props { - onClick: () => void; - isCollapsed: boolean; -} - -export function DocViewTableRowBtnCollapse({ onClick, isCollapsed }: Props) { - const label = i18n.translate('discover.docViews.table.toggleFieldDetails', { - defaultMessage: 'Toggle field details', - }); - return ( - - onClick()} - iconType={isCollapsed ? 'arrowRight' : 'arrowDown'} - iconSize={'s'} - /> - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_add.tsx b/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_add.tsx deleted file mode 100644 index 1707861faf28..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_add.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { FormattedMessage } from '@osd/i18n/react'; -import { EuiToolTip, EuiButtonIcon } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; - -export interface Props { - onClick: () => void; - disabled: boolean; -} - -export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props) { - const tooltipContent = disabled ? ( - - ) : ( - - ); - - return ( - - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_exists.tsx b/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_exists.tsx deleted file mode 100644 index d4f401282e14..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_exists.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { FormattedMessage } from '@osd/i18n/react'; -import { EuiToolTip, EuiButtonIcon } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; - -export interface Props { - onClick: () => void; - disabled?: boolean; - scripted?: boolean; -} - -export function DocViewTableRowBtnFilterExists({ - onClick, - disabled = false, - scripted = false, -}: Props) { - const tooltipContent = disabled ? ( - scripted ? ( - - ) : ( - - ) - ) : ( - - ); - - return ( - - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_remove.tsx b/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_remove.tsx deleted file mode 100644 index 3b58fbfdc282..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_filter_remove.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { FormattedMessage } from '@osd/i18n/react'; -import { EuiToolTip, EuiButtonIcon } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; - -export interface Props { - onClick: () => void; - disabled?: boolean; -} - -export function DocViewTableRowBtnFilterRemove({ onClick, disabled = false }: Props) { - const tooltipContent = disabled ? ( - - ) : ( - - ); - - return ( - - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_toggle_column.tsx b/src/plugins/discover_legacy/public/application/components/table/table_row_btn_toggle_column.tsx deleted file mode 100644 index 74f0972fa0ee..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_row_btn_toggle_column.tsx +++ /dev/null @@ -1,79 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { FormattedMessage } from '@osd/i18n/react'; -import { EuiToolTip, EuiButtonIcon } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; - -export interface Props { - active: boolean; - disabled?: boolean; - onClick: () => void; -} - -export function DocViewTableRowBtnToggleColumn({ onClick, active, disabled = false }: Props) { - if (disabled) { - return ( - - ); - } - return ( - - } - > - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_row_icon_no_mapping.tsx b/src/plugins/discover_legacy/public/application/components/table/table_row_icon_no_mapping.tsx deleted file mode 100644 index edc4bea91bd8..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_row_icon_no_mapping.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiIconTip } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; - -export function DocViewTableRowIconNoMapping() { - const ariaLabel = i18n.translate('discover.docViews.table.noCachedMappingForThisFieldAriaLabel', { - defaultMessage: 'Warning', - }); - const tooltipContent = i18n.translate( - 'discover.docViews.table.noCachedMappingForThisFieldTooltip', - { - defaultMessage: - 'No cached mapping for this field. Refresh field list from the Management > Index Patterns page', - } - ); - return ( - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/table/table_row_icon_underscore.tsx b/src/plugins/discover_legacy/public/application/components/table/table_row_icon_underscore.tsx deleted file mode 100644 index f1d09e2c8d44..000000000000 --- a/src/plugins/discover_legacy/public/application/components/table/table_row_icon_underscore.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { EuiIconTip } from '@elastic/eui'; -import { i18n } from '@osd/i18n'; - -export function DocViewTableRowIconUnderscore() { - const ariaLabel = i18n.translate( - 'discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedAriaLabel', - { - defaultMessage: 'Warning', - } - ); - const tooltipContent = i18n.translate( - 'discover.docViews.table.fieldNamesBeginningWithUnderscoreUnsupportedTooltip', - { - defaultMessage: 'Field names beginning with {underscoreSign} are not supported', - values: { underscoreSign: '_' }, - } - ); - - return ( - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/timechart_header/index.ts b/src/plugins/discover_legacy/public/application/components/timechart_header/index.ts deleted file mode 100644 index 880610ac57e9..000000000000 --- a/src/plugins/discover_legacy/public/application/components/timechart_header/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { TimechartHeader } from './timechart_header'; diff --git a/src/plugins/discover_legacy/public/application/components/timechart_header/timechart_header.test.tsx b/src/plugins/discover_legacy/public/application/components/timechart_header/timechart_header.test.tsx deleted file mode 100644 index 9011c38a6acb..000000000000 --- a/src/plugins/discover_legacy/public/application/components/timechart_header/timechart_header.test.tsx +++ /dev/null @@ -1,110 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { mountWithIntl } from 'test_utils/enzyme_helpers'; -import { ReactWrapper } from 'enzyme'; -import { TimechartHeader, TimechartHeaderProps } from './timechart_header'; -import { EuiIconTip } from '@elastic/eui'; -import { findTestSubject } from 'test_utils/helpers'; - -describe('timechart header', function () { - let props: TimechartHeaderProps; - let component: ReactWrapper; - - beforeAll(() => { - props = { - timeRange: { - from: 'May 14, 2020 @ 11:05:13.590', - to: 'May 14, 2020 @ 11:20:13.590', - }, - stateInterval: 's', - options: [ - { - display: 'Auto', - val: 'auto', - }, - { - display: 'Millisecond', - val: 'ms', - }, - { - display: 'Second', - val: 's', - }, - ], - onChangeInterval: jest.fn(), - bucketInterval: { - scaled: undefined, - description: 'second', - scale: undefined, - }, - }; - }); - - it('TimechartHeader not renders an info text when the showScaledInfo property is not provided', () => { - component = mountWithIntl(); - expect(component.find(EuiIconTip).length).toBe(0); - }); - - it('TimechartHeader renders an info when bucketInterval.scale is set to true', () => { - props.bucketInterval!.scaled = true; - component = mountWithIntl(); - expect(component.find(EuiIconTip).length).toBe(1); - }); - - it('expect to render the date range', function () { - component = mountWithIntl(); - const datetimeRangeText = findTestSubject(component, 'discoverIntervalDateRange'); - expect(datetimeRangeText.text()).toBe( - 'May 14, 2020 @ 11:05:13.590 - May 14, 2020 @ 11:20:13.590 per' - ); - }); - - it('expects to render a dropdown with the interval options', () => { - component = mountWithIntl(); - const dropdown = findTestSubject(component, 'discoverIntervalSelect'); - expect(dropdown.length).toBe(1); - // @ts-ignore - const values = dropdown.find('option').map((option) => option.prop('value')); - expect(values).toEqual(['auto', 'ms', 's']); - // @ts-ignore - const labels = dropdown.find('option').map((option) => option.text()); - expect(labels).toEqual(['Auto', 'Millisecond', 'Second']); - }); - - it('should change the interval', function () { - component = mountWithIntl(); - findTestSubject(component, 'discoverIntervalSelect').simulate('change', { - target: { value: 'ms' }, - }); - expect(props.onChangeInterval).toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/components/timechart_header/timechart_header.tsx b/src/plugins/discover_legacy/public/application/components/timechart_header/timechart_header.tsx deleted file mode 100644 index b73e8b162570..000000000000 --- a/src/plugins/discover_legacy/public/application/components/timechart_header/timechart_header.tsx +++ /dev/null @@ -1,183 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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, { useState, useEffect, useCallback } from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiToolTip, - EuiText, - EuiSelect, - EuiIconTip, -} from '@elastic/eui'; -import { I18nProvider } from '@osd/i18n/react'; -import { i18n } from '@osd/i18n'; -import moment from 'moment'; - -export interface TimechartHeaderProps { - /** - * Format of date to be displayed - */ - dateFormat?: string; - /** - * Interval for the buckets of the recent request - */ - bucketInterval?: { - scaled?: boolean; - description?: string; - scale?: number; - }; - /** - * Range of dates to be displayed - */ - timeRange?: { - from: string; - to: string; - }; - /** - * Interval Options - */ - options: Array<{ display: string; val: string }>; - /** - * changes the interval - */ - onChangeInterval: (interval: string) => void; - /** - * selected interval - */ - stateInterval: string; -} - -export function TimechartHeader({ - bucketInterval, - dateFormat, - timeRange, - options, - onChangeInterval, - stateInterval, -}: TimechartHeaderProps) { - const [interval, setInterval] = useState(stateInterval); - const toMoment = useCallback( - (datetime: string) => { - if (!datetime) { - return ''; - } - if (!dateFormat) { - return datetime; - } - return moment(datetime).format(dateFormat); - }, - [dateFormat] - ); - - useEffect(() => { - setInterval(stateInterval); - }, [stateInterval]); - - const handleIntervalChange = (e: React.ChangeEvent) => { - setInterval(e.target.value); - onChangeInterval(e.target.value); - }; - - if (!timeRange || !bucketInterval) { - return null; - } - - return ( - - - - - - {`${toMoment(timeRange.from)} - ${toMoment(timeRange.to)} ${ - interval !== 'auto' - ? i18n.translate('discover.timechartHeader.timeIntervalSelect.per', { - defaultMessage: 'per', - }) - : '' - }`} - - - - - val !== 'custom') - .map(({ display, val }) => { - return { - text: display, - value: val, - label: display, - }; - })} - value={interval} - onChange={handleIntervalChange} - append={ - bucketInterval.scaled ? ( - 1 - ? i18n.translate('discover.bucketIntervalTooltip.tooLargeBucketsText', { - defaultMessage: 'buckets that are too large', - }) - : i18n.translate('discover.bucketIntervalTooltip.tooManyBucketsText', { - defaultMessage: 'too many buckets', - }), - bucketIntervalDescription: bucketInterval.description, - }, - })} - color="warning" - size="s" - type="alert" - /> - ) : undefined - } - /> - - - - ); -} diff --git a/src/plugins/discover_legacy/public/application/components/top_nav/__snapshots__/open_search_panel.test.js.snap b/src/plugins/discover_legacy/public/application/components/top_nav/__snapshots__/open_search_panel.test.js.snap deleted file mode 100644 index 342dea206c30..000000000000 --- a/src/plugins/discover_legacy/public/application/components/top_nav/__snapshots__/open_search_panel.test.js.snap +++ /dev/null @@ -1,69 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`render 1`] = ` - - - -

- -

-
-
- - - } - onChoose={[Function]} - savedObjectMetaData={ - Array [ - Object { - "getIconForSavedObject": [Function], - "name": "Saved search", - "type": "search", - }, - ] - } - savedObjects={Object {}} - uiSettings={Object {}} - /> - - - - - - - - - - -
-`; diff --git a/src/plugins/discover_legacy/public/application/components/top_nav/open_search_panel.js b/src/plugins/discover_legacy/public/application/components/top_nav/open_search_panel.js deleted file mode 100644 index f575b8dee625..000000000000 --- a/src/plugins/discover_legacy/public/application/components/top_nav/open_search_panel.js +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 PropTypes from 'prop-types'; -import rison from 'rison-node'; -import { i18n } from '@osd/i18n'; -import { FormattedMessage } from '@osd/i18n/react'; -import { - EuiButton, - EuiFlexGroup, - EuiFlexItem, - EuiFlyout, - EuiFlyoutHeader, - EuiFlyoutFooter, - EuiFlyoutBody, - EuiTitle, -} from '@elastic/eui'; -import { SavedObjectFinderUi } from '../../../../../saved_objects/public'; -import { getServices } from '../../../opensearch_dashboards_services'; - -const SEARCH_OBJECT_TYPE = 'search'; - -export function OpenSearchPanel(props) { - const { - core: { uiSettings, savedObjects }, - addBasePath, - } = getServices(); - - return ( - - - -

- -

-
-
- - - } - savedObjectMetaData={[ - { - type: SEARCH_OBJECT_TYPE, - getIconForSavedObject: () => 'search', - name: i18n.translate('discover.savedSearch.savedObjectName', { - defaultMessage: 'Saved search', - }), - }, - ]} - onChoose={(id) => { - window.location.assign(props.makeUrl(id)); - props.onClose(); - }} - uiSettings={uiSettings} - savedObjects={savedObjects} - /> - - - - - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - - - - - - -
- ); -} - -OpenSearchPanel.propTypes = { - onClose: PropTypes.func.isRequired, - makeUrl: PropTypes.func.isRequired, -}; diff --git a/src/plugins/discover_legacy/public/application/components/top_nav/open_search_panel.test.js b/src/plugins/discover_legacy/public/application/components/top_nav/open_search_panel.test.js deleted file mode 100644 index 6316471e9a40..000000000000 --- a/src/plugins/discover_legacy/public/application/components/top_nav/open_search_panel.test.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { shallow } from 'enzyme'; - -jest.mock('../../../opensearch_dashboards_services', () => { - return { - getServices: () => ({ - core: { uiSettings: {}, savedObjects: {} }, - addBasePath: (path) => path, - }), - }; -}); - -import { OpenSearchPanel } from './open_search_panel'; - -test('render', () => { - const component = shallow( {}} makeUrl={() => {}} />); - expect(component).toMatchSnapshot(); -}); diff --git a/src/plugins/discover_legacy/public/application/components/top_nav/show_open_search_panel.js b/src/plugins/discover_legacy/public/application/components/top_nav/show_open_search_panel.js deleted file mode 100644 index 8cb550f49f16..000000000000 --- a/src/plugins/discover_legacy/public/application/components/top_nav/show_open_search_panel.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 ReactDOM from 'react-dom'; -import { OpenSearchPanel } from './open_search_panel'; - -let isOpen = false; - -export function showOpenSearchPanel({ makeUrl, I18nContext }) { - if (isOpen) { - return; - } - - isOpen = true; - const container = document.createElement('div'); - const onClose = () => { - ReactDOM.unmountComponentAtNode(container); - document.body.removeChild(container); - isOpen = false; - }; - - document.body.appendChild(container); - const element = ( - - - - ); - ReactDOM.render(element, container); -} diff --git a/src/plugins/discover_legacy/public/application/doc_views/doc_views_helpers.tsx b/src/plugins/discover_legacy/public/application/doc_views/doc_views_helpers.tsx deleted file mode 100644 index e113f6961fc3..000000000000 --- a/src/plugins/discover_legacy/public/application/doc_views/doc_views_helpers.tsx +++ /dev/null @@ -1,105 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { auto, IController } from 'angular'; -import React from 'react'; -import { render } from 'react-dom'; -import angular, { ICompileService } from 'angular'; -import { DocViewRenderProps, AngularScope, AngularDirective } from './doc_views_types'; -import { DocViewerError } from '../components/doc_viewer/doc_viewer_render_error'; - -/** - * Compiles and injects the give angular template into the given dom node - * returns a function to cleanup the injected angular element - */ -export async function injectAngularElement( - domNode: Element, - template: string, - scopeProps: DocViewRenderProps, - Controller: IController, - getInjector: () => Promise -): Promise<() => void> { - const $injector = await getInjector(); - const rootScope: AngularScope = $injector.get('$rootScope'); - const $compile: ICompileService = $injector.get('$compile'); - const newScope = Object.assign(rootScope.$new(), scopeProps); - - if (typeof Controller === 'function') { - // when a controller is defined, expose the value it produces to the view as `$ctrl` - // see: https://docs.angularjs.org/api/ng/provider/$compileProvider#component - (newScope as any).$ctrl = $injector.instantiate(Controller, { - $scope: newScope, - }); - } - - const $target = angular.element(domNode); - const $element = angular.element(template); - - newScope.$apply(() => { - const linkFn = $compile($element); - $target.empty().append($element); - linkFn(newScope); - }); - - return () => { - newScope.$destroy(); - }; -} -/** - * Converts a given legacy angular directive to a render function - * for usage in a react component. Note that the rendering is async - */ -export function convertDirectiveToRenderFn( - directive: AngularDirective, - getInjector: () => Promise -) { - return (domNode: Element, props: DocViewRenderProps) => { - let rejected = false; - - const cleanupFnPromise = injectAngularElement( - domNode, - directive.template, - props, - directive.controller, - getInjector - ); - cleanupFnPromise.catch((e) => { - rejected = true; - render(, domNode); - }); - - return () => { - if (!rejected) { - // for cleanup - cleanupFnPromise.then((cleanup) => cleanup()); - } - }; - }; -} diff --git a/src/plugins/discover_legacy/public/application/doc_views/doc_views_registry.ts b/src/plugins/discover_legacy/public/application/doc_views/doc_views_registry.ts deleted file mode 100644 index 56f167b5f2cc..000000000000 --- a/src/plugins/discover_legacy/public/application/doc_views/doc_views_registry.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { auto } from 'angular'; -import { convertDirectiveToRenderFn } from './doc_views_helpers'; -import { DocView, DocViewInput, OpenSearchSearchHit, DocViewInputFn } from './doc_views_types'; - -export class DocViewsRegistry { - private docViews: DocView[] = []; - private angularInjectorGetter: (() => Promise) | null = null; - - setAngularInjectorGetter = (injectorGetter: () => Promise) => { - this.angularInjectorGetter = injectorGetter; - }; - - /** - * Extends and adds the given doc view to the registry array - */ - addDocView(docViewRaw: DocViewInput | DocViewInputFn) { - const docView = typeof docViewRaw === 'function' ? docViewRaw() : docViewRaw; - if (docView.directive) { - // convert angular directive to render function for backwards compatibility - docView.render = convertDirectiveToRenderFn(docView.directive, () => { - if (!this.angularInjectorGetter) { - throw new Error('Angular was not initialized'); - } - return this.angularInjectorGetter(); - }); - } - if (typeof docView.shouldShow !== 'function') { - docView.shouldShow = () => true; - } - this.docViews.push(docView as DocView); - } - /** - * Returns a sorted array of doc_views for rendering tabs - */ - getDocViewsSorted(hit: OpenSearchSearchHit) { - return this.docViews - .filter((docView) => docView.shouldShow(hit)) - .sort((a, b) => (Number(a.order) > Number(b.order) ? 1 : -1)); - } -} diff --git a/src/plugins/discover_legacy/public/application/doc_views/doc_views_types.ts b/src/plugins/discover_legacy/public/application/doc_views/doc_views_types.ts deleted file mode 100644 index 961fc98516f6..000000000000 --- a/src/plugins/discover_legacy/public/application/doc_views/doc_views_types.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { ComponentType } from 'react'; -import { IScope } from 'angular'; -import { SearchResponse } from 'elasticsearch'; -import { IndexPattern } from '../../../../data/public'; - -export interface AngularDirective { - controller: (...injectedServices: any[]) => void; - template: string; -} - -export type AngularScope = IScope; - -export type OpenSearchSearchHit = SearchResponse['hits']['hits'][number]; - -export interface FieldMapping { - filterable?: boolean; - scripted?: boolean; - rowCount?: number; - type: string; - name: string; -} - -export type DocViewFilterFn = ( - mapping: FieldMapping | string | undefined, - value: unknown, - mode: '+' | '-' -) => void; - -export interface DocViewRenderProps { - columns?: string[]; - filter?: DocViewFilterFn; - hit: OpenSearchSearchHit; - indexPattern: IndexPattern; - onAddColumn?: (columnName: string) => void; - onRemoveColumn?: (columnName: string) => void; -} -export type DocViewerComponent = ComponentType; -export type DocViewRenderFn = ( - domeNode: HTMLDivElement, - renderProps: DocViewRenderProps -) => () => void; - -export interface DocViewInput { - component?: DocViewerComponent; - directive?: AngularDirective; - order: number; - render?: DocViewRenderFn; - shouldShow?: (hit: OpenSearchSearchHit) => boolean; - title: string; -} - -export interface DocView extends DocViewInput { - shouldShow: (hit: OpenSearchSearchHit) => boolean; -} - -export type DocViewInputFn = () => DocViewInput; diff --git a/src/plugins/discover_legacy/public/application/doc_views_links/doc_views_links_registry.ts b/src/plugins/discover_legacy/public/application/doc_views_links/doc_views_links_registry.ts deleted file mode 100644 index 16653f5d5377..000000000000 --- a/src/plugins/discover_legacy/public/application/doc_views_links/doc_views_links_registry.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { DocViewLink } from './doc_views_links_types'; - -export class DocViewsLinksRegistry { - private docViewsLinks: DocViewLink[] = []; - - addDocViewLink(docViewLink: DocViewLink) { - this.docViewsLinks.push(docViewLink); - } - - getDocViewsLinksSorted() { - return this.docViewsLinks.sort((a, b) => (Number(a.order) > Number(b.order) ? 1 : -1)); - } -} diff --git a/src/plugins/discover_legacy/public/application/doc_views_links/doc_views_links_types.ts b/src/plugins/discover_legacy/public/application/doc_views_links/doc_views_links_types.ts deleted file mode 100644 index bbc5caadafcd..000000000000 --- a/src/plugins/discover_legacy/public/application/doc_views_links/doc_views_links_types.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { EuiListGroupItemProps } from '@elastic/eui'; -import { OpenSearchSearchHit } from '../doc_views/doc_views_types'; -import { IndexPattern } from '../../../../data/public'; - -export interface DocViewLink extends EuiListGroupItemProps { - href?: string; - order: number; - generateCb?( - renderProps: any - ): { - url: string; - hide?: boolean; - }; -} - -export interface DocViewLinkRenderProps { - columns?: string[]; - hit: OpenSearchSearchHit; - indexPattern: IndexPattern; -} diff --git a/src/plugins/discover_legacy/public/application/embeddable/constants.ts b/src/plugins/discover_legacy/public/application/embeddable/constants.ts deleted file mode 100644 index 82f428ea4e4b..000000000000 --- a/src/plugins/discover_legacy/public/application/embeddable/constants.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 SEARCH_EMBEDDABLE_TYPE = 'search'; diff --git a/src/plugins/discover_legacy/public/application/embeddable/index.ts b/src/plugins/discover_legacy/public/application/embeddable/index.ts deleted file mode 100644 index ecb5e98f43c1..000000000000 --- a/src/plugins/discover_legacy/public/application/embeddable/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { SEARCH_EMBEDDABLE_TYPE } from './constants'; -export * from './types'; -export * from './search_embeddable_factory'; diff --git a/src/plugins/discover_legacy/public/application/embeddable/search_embeddable.scss b/src/plugins/discover_legacy/public/application/embeddable/search_embeddable.scss deleted file mode 100644 index e953968495e7..000000000000 --- a/src/plugins/discover_legacy/public/application/embeddable/search_embeddable.scss +++ /dev/null @@ -1,12 +0,0 @@ -/** - * 1. We want the osdDocTable__container to scroll only when embedded in an embeddable panel - * 2. Force a better looking scrollbar - */ -.embPanel { - .osdDocTable__container { - @include euiScrollBar; /* 2 */ - - flex: 1 1 0; /* 1 */ - overflow: auto; /* 1 */ - } -} diff --git a/src/plugins/discover_legacy/public/application/embeddable/search_embeddable.ts b/src/plugins/discover_legacy/public/application/embeddable/search_embeddable.ts deleted file mode 100644 index 933f807f8153..000000000000 --- a/src/plugins/discover_legacy/public/application/embeddable/search_embeddable.ts +++ /dev/null @@ -1,361 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 './search_embeddable.scss'; -import angular from 'angular'; -import _ from 'lodash'; -import * as Rx from 'rxjs'; -import { Subscription } from 'rxjs'; -import { i18n } from '@osd/i18n'; -import { UiActionsStart, APPLY_FILTER_TRIGGER } from '../../../../ui_actions/public'; -import { RequestAdapter, Adapters } from '../../../../inspector/public'; -import { - opensearchFilters, - Filter, - TimeRange, - FilterManager, - getTime, - Query, - IFieldType, -} from '../../../../data/public'; -import { Container, Embeddable } from '../../../../embeddable/public'; -import * as columnActions from '../angular/doc_table/actions/columns'; -import searchTemplate from './search_template.html'; -import { ISearchEmbeddable, SearchInput, SearchOutput } from './types'; -import { SortOrder } from '../angular/doc_table/components/table_header/helpers'; -import { getSortForSearchSource } from '../angular/doc_table'; -import { - getRequestInspectorStats, - getResponseInspectorStats, - getServices, - IndexPattern, - ISearchSource, -} from '../../opensearch_dashboards_services'; -import { SEARCH_EMBEDDABLE_TYPE } from './constants'; -import { SavedSearch } from '../..'; -import { SAMPLE_SIZE_SETTING, SORT_DEFAULT_ORDER_SETTING } from '../../../common'; - -interface SearchScope extends ng.IScope { - columns?: string[]; - description?: string; - sort?: SortOrder[]; - sharedItemTitle?: string; - inspectorAdapters?: Adapters; - setSortOrder?: (sortPair: SortOrder[]) => void; - removeColumn?: (column: string) => void; - addColumn?: (column: string) => void; - moveColumn?: (column: string, index: number) => void; - filter?: (field: IFieldType, value: string[], operator: string) => void; - hits?: any[]; - indexPattern?: IndexPattern; - totalHitCount?: number; - isLoading?: boolean; -} - -interface SearchEmbeddableConfig { - $rootScope: ng.IRootScopeService; - $compile: ng.ICompileService; - savedSearch: SavedSearch; - editUrl: string; - editPath: string; - indexPatterns?: IndexPattern[]; - editable: boolean; - filterManager: FilterManager; -} - -export class SearchEmbeddable - extends Embeddable - implements ISearchEmbeddable { - private readonly savedSearch: SavedSearch; - private $rootScope: ng.IRootScopeService; - private $compile: ng.ICompileService; - private inspectorAdaptors: Adapters; - private searchScope?: SearchScope; - private panelTitle: string = ''; - private filtersSearchSource?: ISearchSource; - private searchInstance?: JQLite; - private autoRefreshFetchSubscription?: Subscription; - private subscription?: Subscription; - public readonly type = SEARCH_EMBEDDABLE_TYPE; - private filterManager: FilterManager; - private abortController?: AbortController; - - private prevTimeRange?: TimeRange; - private prevFilters?: Filter[]; - private prevQuery?: Query; - - constructor( - { - $rootScope, - $compile, - savedSearch, - editUrl, - editPath, - indexPatterns, - editable, - filterManager, - }: SearchEmbeddableConfig, - initialInput: SearchInput, - private readonly executeTriggerActions: UiActionsStart['executeTriggerActions'], - parent?: Container - ) { - super( - initialInput, - { - defaultTitle: savedSearch.title, - editUrl, - editPath, - editApp: 'discover', - indexPatterns, - editable, - }, - parent - ); - - this.filterManager = filterManager; - this.savedSearch = savedSearch; - this.$rootScope = $rootScope; - this.$compile = $compile; - this.inspectorAdaptors = { - requests: new RequestAdapter(), - }; - this.initializeSearchScope(); - - this.autoRefreshFetchSubscription = getServices() - .timefilter.getAutoRefreshFetch$() - .subscribe(this.fetch); - - this.subscription = Rx.merge(this.getOutput$(), this.getInput$()).subscribe(() => { - this.panelTitle = this.output.title || ''; - - if (this.searchScope) { - this.pushContainerStateParamsToScope(this.searchScope); - } - }); - } - - public getInspectorAdapters() { - return this.inspectorAdaptors; - } - - public getSavedSearch() { - return this.savedSearch; - } - - /** - * - * @param {Element} domNode - */ - public render(domNode: HTMLElement) { - if (!this.searchScope) { - throw new Error('Search scope not defined'); - } - this.searchInstance = this.$compile(searchTemplate)(this.searchScope); - const rootNode = angular.element(domNode); - rootNode.append(this.searchInstance); - - this.pushContainerStateParamsToScope(this.searchScope); - } - - public destroy() { - super.destroy(); - this.savedSearch.destroy(); - if (this.searchInstance) { - this.searchInstance.remove(); - } - if (this.searchScope) { - this.searchScope.$destroy(); - delete this.searchScope; - } - if (this.subscription) { - this.subscription.unsubscribe(); - } - if (this.autoRefreshFetchSubscription) { - this.autoRefreshFetchSubscription.unsubscribe(); - } - if (this.abortController) this.abortController.abort(); - } - - private initializeSearchScope() { - const searchScope: SearchScope = (this.searchScope = this.$rootScope.$new()); - - searchScope.description = this.savedSearch.description; - searchScope.inspectorAdapters = this.inspectorAdaptors; - - const { searchSource } = this.savedSearch; - const indexPattern = (searchScope.indexPattern = searchSource.getField('index'))!; - - const timeRangeSearchSource = searchSource.create(); - timeRangeSearchSource.setField('filter', () => { - if (!this.searchScope || !this.input.timeRange) return; - return getTime(indexPattern, this.input.timeRange); - }); - - this.filtersSearchSource = searchSource.create(); - this.filtersSearchSource.setParent(timeRangeSearchSource); - - searchSource.setParent(this.filtersSearchSource); - - this.pushContainerStateParamsToScope(searchScope); - - searchScope.setSortOrder = (sort) => { - this.updateInput({ sort }); - }; - - searchScope.addColumn = (columnName: string) => { - if (!searchScope.columns) { - return; - } - const columns = columnActions.addColumn(searchScope.columns, columnName); - this.updateInput({ columns }); - }; - - searchScope.removeColumn = (columnName: string) => { - if (!searchScope.columns) { - return; - } - const columns = columnActions.removeColumn(searchScope.columns, columnName); - this.updateInput({ columns }); - }; - - searchScope.moveColumn = (columnName, newIndex: number) => { - if (!searchScope.columns) { - return; - } - const columns = columnActions.moveColumn(searchScope.columns, columnName, newIndex); - this.updateInput({ columns }); - }; - - searchScope.filter = async (field, value, operator) => { - let filters = opensearchFilters.generateFilters( - this.filterManager, - field, - value, - operator, - indexPattern.id! - ); - filters = filters.map((filter) => ({ - ...filter, - $state: { store: opensearchFilters.FilterStateStore.APP_STATE }, - })); - - await this.executeTriggerActions(APPLY_FILTER_TRIGGER, { - embeddable: this, - filters, - }); - }; - } - - public reload() { - this.fetch(); - } - - private fetch = async () => { - if (!this.searchScope) return; - - const { searchSource } = this.savedSearch; - - // Abort any in-progress requests - if (this.abortController) this.abortController.abort(); - this.abortController = new AbortController(); - - searchSource.setField('size', getServices().uiSettings.get(SAMPLE_SIZE_SETTING)); - searchSource.setField( - 'sort', - getSortForSearchSource( - this.searchScope.sort, - this.searchScope.indexPattern, - getServices().uiSettings.get(SORT_DEFAULT_ORDER_SETTING) - ) - ); - - // Log request to inspector - this.inspectorAdaptors.requests.reset(); - const title = i18n.translate('discover.embeddable.inspectorRequestDataTitle', { - defaultMessage: 'Data', - }); - const description = i18n.translate('discover.embeddable.inspectorRequestDescription', { - defaultMessage: 'This request queries OpenSearch to fetch the data for the search.', - }); - const inspectorRequest = this.inspectorAdaptors.requests.start(title, { description }); - inspectorRequest.stats(getRequestInspectorStats(searchSource)); - searchSource.getSearchRequestBody().then((body: Record) => { - inspectorRequest.json(body); - }); - this.updateOutput({ loading: true, error: undefined }); - - try { - // Make the request - const resp = await searchSource.fetch({ - abortSignal: this.abortController.signal, - }); - this.updateOutput({ loading: false, error: undefined }); - - // Log response to inspector - inspectorRequest.stats(getResponseInspectorStats(resp, searchSource)).ok({ json: resp }); - - // Apply the changes to the angular scope - this.searchScope.$apply(() => { - this.searchScope!.hits = resp.hits.hits; - this.searchScope!.totalHitCount = resp.hits.total; - }); - } catch (error) { - this.updateOutput({ loading: false, error }); - } - }; - - private pushContainerStateParamsToScope(searchScope: SearchScope) { - const isFetchRequired = - !opensearchFilters.onlyDisabledFiltersChanged(this.input.filters, this.prevFilters) || - !_.isEqual(this.prevQuery, this.input.query) || - !_.isEqual(this.prevTimeRange, this.input.timeRange) || - !_.isEqual(searchScope.sort, this.input.sort || this.savedSearch.sort); - - // If there is column or sort data on the panel, that means the original columns or sort settings have - // been overridden in a dashboard. - searchScope.columns = this.input.columns || this.savedSearch.columns; - searchScope.sort = this.input.sort || this.savedSearch.sort; - searchScope.sharedItemTitle = this.panelTitle; - - if (isFetchRequired) { - this.filtersSearchSource!.setField('filter', this.input.filters); - this.filtersSearchSource!.setField('query', this.input.query); - - this.fetch(); - - this.prevFilters = this.input.filters; - this.prevQuery = this.input.query; - this.prevTimeRange = this.input.timeRange; - } else if (this.searchScope) { - // trigger a digest cycle to make sure non-fetch relevant changes are propagated - this.searchScope.$applyAsync(); - } - } -} diff --git a/src/plugins/discover_legacy/public/application/embeddable/search_embeddable_factory.ts b/src/plugins/discover_legacy/public/application/embeddable/search_embeddable_factory.ts deleted file mode 100644 index 9b8c540713ce..000000000000 --- a/src/plugins/discover_legacy/public/application/embeddable/search_embeddable_factory.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { auto } from 'angular'; -import { i18n } from '@osd/i18n'; -import { UiActionsStart } from 'src/plugins/ui_actions/public'; -import { getServices } from '../../opensearch_dashboards_services'; -import { - EmbeddableFactoryDefinition, - Container, - ErrorEmbeddable, -} from '../../../../embeddable/public'; - -import { TimeRange } from '../../../../data/public'; - -import { SearchInput, SearchOutput, SearchEmbeddable } from './types'; -import { SEARCH_EMBEDDABLE_TYPE } from './constants'; - -interface StartServices { - executeTriggerActions: UiActionsStart['executeTriggerActions']; - isEditable: () => boolean; -} - -export class SearchEmbeddableFactory - implements EmbeddableFactoryDefinition { - public readonly type = SEARCH_EMBEDDABLE_TYPE; - private $injector: auto.IInjectorService | null; - private getInjector: () => Promise | null; - public readonly savedObjectMetaData = { - name: i18n.translate('discover.savedSearch.savedObjectName', { - defaultMessage: 'Saved search', - }), - type: 'search', - getIconForSavedObject: () => 'search', - }; - - constructor( - private getStartServices: () => Promise, - getInjector: () => Promise - ) { - this.$injector = null; - this.getInjector = getInjector; - } - - public canCreateNew() { - return false; - } - - public isEditable = async () => { - return (await this.getStartServices()).isEditable(); - }; - - public getDisplayName() { - return i18n.translate('discover.embeddable.search.displayName', { - defaultMessage: 'search', - }); - } - - public createFromSavedObject = async ( - savedObjectId: string, - input: Partial & { id: string; timeRange: TimeRange }, - parent?: Container - ): Promise => { - if (!this.$injector) { - this.$injector = await this.getInjector(); - } - const $injector = this.$injector as auto.IInjectorService; - - const $compile = $injector.get('$compile'); - const $rootScope = $injector.get('$rootScope'); - const filterManager = getServices().filterManager; - - const url = await getServices().getSavedSearchUrlById(savedObjectId); - const editUrl = getServices().addBasePath(`/app/discover${url}`); - try { - const savedObject = await getServices().getSavedSearchById(savedObjectId); - const indexPattern = savedObject.searchSource.getField('index'); - const { executeTriggerActions } = await this.getStartServices(); - const { SearchEmbeddable: SearchEmbeddableClass } = await import('./search_embeddable'); - return new SearchEmbeddableClass( - { - savedSearch: savedObject, - $rootScope, - $compile, - editUrl, - editPath: url, - filterManager, - editable: getServices().capabilities.discover.save as boolean, - indexPatterns: indexPattern ? [indexPattern] : [], - }, - input, - executeTriggerActions, - parent - ); - } catch (e) { - console.error(e); // eslint-disable-line no-console - return new ErrorEmbeddable(e, input, parent); - } - }; - - public async create(input: SearchInput) { - return new ErrorEmbeddable('Saved searches can only be created from a saved object', input); - } -} diff --git a/src/plugins/discover_legacy/public/application/embeddable/search_template.html b/src/plugins/discover_legacy/public/application/embeddable/search_template.html deleted file mode 100644 index e188d230ea30..000000000000 --- a/src/plugins/discover_legacy/public/application/embeddable/search_template.html +++ /dev/null @@ -1,20 +0,0 @@ - - diff --git a/src/plugins/discover_legacy/public/application/embeddable/types.ts b/src/plugins/discover_legacy/public/application/embeddable/types.ts deleted file mode 100644 index 864f954588dd..000000000000 --- a/src/plugins/discover_legacy/public/application/embeddable/types.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { - Embeddable, - EmbeddableInput, - EmbeddableOutput, - IEmbeddable, -} from 'src/plugins/embeddable/public'; -import { SortOrder } from '../angular/doc_table/components/table_header/helpers'; -import { Filter, IIndexPattern, TimeRange, Query } from '../../../../data/public'; -import { SavedSearch } from '../..'; - -export interface SearchInput extends EmbeddableInput { - timeRange: TimeRange; - query?: Query; - filters?: Filter[]; - hidePanelTitles?: boolean; - columns?: string[]; - sort?: SortOrder[]; -} - -export interface SearchOutput extends EmbeddableOutput { - editUrl: string; - indexPatterns?: IIndexPattern[]; - editable: boolean; -} - -export interface ISearchEmbeddable extends IEmbeddable { - getSavedSearch(): SavedSearch; -} - -export interface SearchEmbeddable extends Embeddable { - type: string; -} diff --git a/src/plugins/discover_legacy/public/application/helpers/breadcrumbs.ts b/src/plugins/discover_legacy/public/application/helpers/breadcrumbs.ts deleted file mode 100644 index e30f50206aef..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/breadcrumbs.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; - -export function getRootBreadcrumbs() { - return [ - { - text: i18n.translate('discover.rootBreadcrumb', { - defaultMessage: 'Discover', - }), - href: '#/', - }, - ]; -} - -export function getSavedSearchBreadcrumbs($route: any) { - return [ - ...getRootBreadcrumbs(), - { - text: $route.current.locals.savedObjects.savedSearch.id, - }, - ]; -} diff --git a/src/plugins/discover_legacy/public/application/helpers/format_number_with_commas.ts b/src/plugins/discover_legacy/public/application/helpers/format_number_with_commas.ts deleted file mode 100644 index b1b3c96e0958..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/format_number_with_commas.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -const COMMA_SEPARATOR_RE = /(\d)(?=(\d{3})+(?!\d))/g; - -/** - * Converts a number to a string and adds commas - * as thousands separators - */ -export const formatNumWithCommas = (input: number) => - String(input).replace(COMMA_SEPARATOR_RE, '$1,'); diff --git a/src/plugins/discover_legacy/public/application/helpers/get_index_pattern_id.ts b/src/plugins/discover_legacy/public/application/helpers/get_index_pattern_id.ts deleted file mode 100644 index dfb02c0b0740..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/get_index_pattern_id.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { IIndexPattern } from '../../../../data/common/index_patterns'; - -export function findIndexPatternById( - indexPatterns: IIndexPattern[], - id: string -): IIndexPattern | undefined { - if (!Array.isArray(indexPatterns) || !id) { - return; - } - return indexPatterns.find((o) => o.id === id); -} - -/** - * Checks if the given defaultIndex exists and returns - * the first available index pattern id if not - */ -export function getFallbackIndexPatternId( - indexPatterns: IIndexPattern[], - defaultIndex: string = '' -): string { - if (defaultIndex && findIndexPatternById(indexPatterns, defaultIndex)) { - return defaultIndex; - } - return !indexPatterns || !indexPatterns.length || !indexPatterns[0].id ? '' : indexPatterns[0].id; -} - -/** - * A given index pattern id is checked for existence and a fallback is provided if it doesn't exist - * The provided defaultIndex is usually configured in Advanced Settings, if it's also invalid - * the first entry of the given list of Indexpatterns is used - */ -export function getIndexPatternId( - id: string = '', - indexPatterns: IIndexPattern[], - defaultIndex: string = '' -): string { - if (!id || !findIndexPatternById(indexPatterns, id)) { - return getFallbackIndexPatternId(indexPatterns, defaultIndex); - } - return id; -} diff --git a/src/plugins/discover_legacy/public/application/helpers/get_switch_index_pattern_app_state.test.ts b/src/plugins/discover_legacy/public/application/helpers/get_switch_index_pattern_app_state.test.ts deleted file mode 100644 index c1a8acb04ac3..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/get_switch_index_pattern_app_state.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getSwitchIndexPatternAppState } from './get_switch_index_pattern_app_state'; -import { IIndexPatternFieldList, IndexPattern } from '../../../../data/common/index_patterns'; - -const currentIndexPattern: IndexPattern = { - id: 'prev', - getFieldByName(name) { - return this.fields.getByName(name); - }, - fields: { - getByName: (name: string) => { - const fields = [ - { name: 'category', sortable: true }, - { name: 'name', sortable: true }, - ] as IIndexPatternFieldList; - return fields.find((field) => field.name === name); - }, - }, -} as IndexPattern; - -const nextIndexPattern = { - id: 'next', - getFieldByName(name) { - return this.fields.getByName(name); - }, - fields: { - getByName: (name: string) => { - const fields = [{ name: 'category', sortable: true }] as IIndexPatternFieldList; - return fields.find((field) => field.name === name); - }, - }, -} as IndexPattern; - -describe('Discover getSwitchIndexPatternAppState', () => { - test('removing fields that are not part of the next index pattern, keeping unknown fields ', async () => { - const result = getSwitchIndexPatternAppState( - currentIndexPattern, - nextIndexPattern, - ['category', 'name', 'unknown'], - [['category', 'desc']] - ); - expect(result.columns).toEqual(['category', 'unknown']); - expect(result.sort).toEqual([['category', 'desc']]); - }); - test('removing sorted by fields that are not part of the next index pattern', async () => { - const result = getSwitchIndexPatternAppState( - currentIndexPattern, - nextIndexPattern, - ['name'], - [ - ['category', 'desc'], - ['name', 'asc'], - ] - ); - expect(result.columns).toEqual(['_source']); - expect(result.sort).toEqual([['category', 'desc']]); - }); - test('removing sorted by fields that without modifying columns', async () => { - const result = getSwitchIndexPatternAppState( - currentIndexPattern, - nextIndexPattern, - ['name'], - [ - ['category', 'desc'], - ['name', 'asc'], - ], - false - ); - expect(result.columns).toEqual(['name']); - expect(result.sort).toEqual([['category', 'desc']]); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/helpers/get_switch_index_pattern_app_state.ts b/src/plugins/discover_legacy/public/application/helpers/get_switch_index_pattern_app_state.ts deleted file mode 100644 index 51835910a402..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/get_switch_index_pattern_app_state.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { getSortArray } from '../angular/doc_table'; -import { SortPairArr } from '../angular/doc_table/lib/get_sort'; -import { IndexPattern } from '../../opensearch_dashboards_services'; - -/** - * Helper function to remove or adapt the currently selected columns/sort to be valid with the next - * index pattern, returns a new state object - */ -export function getSwitchIndexPatternAppState( - currentIndexPattern: IndexPattern, - nextIndexPattern: IndexPattern, - currentColumns: string[], - currentSort: SortPairArr[], - modifyColumns: boolean = true -) { - const nextColumns = modifyColumns - ? currentColumns.filter( - (column) => - nextIndexPattern.fields.getByName(column) || !currentIndexPattern.fields.getByName(column) - ) - : currentColumns; - const nextSort = getSortArray(currentSort, nextIndexPattern); - return { - index: nextIndexPattern.id, - columns: nextColumns.length ? nextColumns : ['_source'], - sort: nextSort, - }; -} diff --git a/src/plugins/discover_legacy/public/application/helpers/index.ts b/src/plugins/discover_legacy/public/application/helpers/index.ts deleted file mode 100644 index d765fdf60cee..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { shortenDottedString } from './shorten_dotted_string'; -export { formatNumWithCommas } from './format_number_with_commas'; diff --git a/src/plugins/discover_legacy/public/application/helpers/migrate_legacy_query.ts b/src/plugins/discover_legacy/public/application/helpers/migrate_legacy_query.ts deleted file mode 100644 index 90458c135b98..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/migrate_legacy_query.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { has } from 'lodash'; -import { Query } from 'src/plugins/data/public'; - -/** - * Creates a standardized query object from old queries that were either strings or pure OpenSearch query DSL - * - * @param query - a legacy query, what used to be stored in SearchSource's query property - * @return Object - */ - -export function migrateLegacyQuery(query: Query | { [key: string]: any } | string): Query { - // Lucene was the only option before, so language-less queries are all lucene - if (!has(query, 'language')) { - return { query, language: 'lucene' }; - } - - return query as Query; -} diff --git a/src/plugins/discover_legacy/public/application/helpers/popularize_field.test.ts b/src/plugins/discover_legacy/public/application/helpers/popularize_field.test.ts deleted file mode 100644 index cdd49c0f77f1..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/popularize_field.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { IndexPattern, IndexPatternsService } from '../../../../data/public'; -import { popularizeField } from './popularize_field'; - -describe('Popularize field', () => { - test('returns undefined if index pattern lacks id', async () => { - const indexPattern = ({} as unknown) as IndexPattern; - const fieldName = '@timestamp'; - const indexPatternsService = ({} as unknown) as IndexPatternsService; - const result = await popularizeField(indexPattern, fieldName, indexPatternsService); - expect(result).toBeUndefined(); - }); - - test('returns undefined if field not found', async () => { - const indexPattern = ({ - fields: { - getByName: () => {}, - }, - } as unknown) as IndexPattern; - const fieldName = '@timestamp'; - const indexPatternsService = ({} as unknown) as IndexPatternsService; - const result = await popularizeField(indexPattern, fieldName, indexPatternsService); - expect(result).toBeUndefined(); - }); - - test('returns undefined if successful', async () => { - const field = { - count: 0, - }; - const indexPattern = ({ - id: 'id', - fields: { - getByName: () => field, - }, - } as unknown) as IndexPattern; - const fieldName = '@timestamp'; - const indexPatternsService = ({ - updateSavedObject: async () => {}, - } as unknown) as IndexPatternsService; - const result = await popularizeField(indexPattern, fieldName, indexPatternsService); - expect(result).toBeUndefined(); - expect(field.count).toEqual(1); - }); - - test('hides errors', async () => { - const field = { - count: 0, - }; - const indexPattern = ({ - id: 'id', - fields: { - getByName: () => field, - }, - } as unknown) as IndexPattern; - const fieldName = '@timestamp'; - const indexPatternsService = ({ - updateSavedObject: async () => { - throw new Error('unknown error'); - }, - } as unknown) as IndexPatternsService; - const result = await popularizeField(indexPattern, fieldName, indexPatternsService); - expect(result).toBeUndefined(); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/helpers/popularize_field.ts b/src/plugins/discover_legacy/public/application/helpers/popularize_field.ts deleted file mode 100644 index e7c4b900fa19..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/popularize_field.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { IndexPattern, IndexPatternsService } from '../../../../data/public'; - -async function popularizeField( - indexPattern: IndexPattern, - fieldName: string, - indexPatternsService: IndexPatternsService -) { - if (!indexPattern.id) return; - const field = indexPattern.fields.getByName(fieldName); - if (!field) { - return; - } - - field.count++; - // Catch 409 errors caused by user adding columns in a higher frequency that the changes can be persisted to OpenSearch - try { - await indexPatternsService.updateSavedObject(indexPattern, 0, true); - // eslint-disable-next-line no-empty - } catch {} -} - -export { popularizeField }; diff --git a/src/plugins/discover_legacy/public/application/helpers/shorten_dotted_string.ts b/src/plugins/discover_legacy/public/application/helpers/shorten_dotted_string.ts deleted file mode 100644 index 39450f8c82c0..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/shorten_dotted_string.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -const DOT_PREFIX_RE = /(.).+?\./g; - -/** - * Convert a dot.notated.string into a short - * version (d.n.string) - */ -export const shortenDottedString = (input: string) => input.replace(DOT_PREFIX_RE, '$1.'); diff --git a/src/plugins/discover_legacy/public/application/helpers/validate_time_range.test.ts b/src/plugins/discover_legacy/public/application/helpers/validate_time_range.test.ts deleted file mode 100644 index 902f3d8a4b62..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/validate_time_range.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { validateTimeRange } from './validate_time_range'; -import { notificationServiceMock } from '../../../../../core/public/mocks'; - -describe('Discover validateTimeRange', () => { - test('validates given time ranges correctly', async () => { - const { toasts } = notificationServiceMock.createStartContract(); - [ - { from: '', to: '', result: false }, - { from: 'now', to: 'now+1h', result: true }, - { from: 'now', to: 'lala+1h', result: false }, - { from: '', to: 'now', result: false }, - { from: 'now', to: '', result: false }, - { from: ' 2020-06-02T13:36:13.689Z', to: 'now', result: true }, - { from: ' 2020-06-02T13:36:13.689Z', to: '2020-06-02T13:36:13.690Z', result: true }, - ].map((test) => { - expect(validateTimeRange({ from: test.from, to: test.to }, toasts)).toEqual(test.result); - }); - }); - - test('displays a toast when invalid data is entered', async () => { - const { toasts } = notificationServiceMock.createStartContract(); - expect(validateTimeRange({ from: 'now', to: 'null' }, toasts)).toEqual(false); - expect(toasts.addDanger).toHaveBeenCalledWith({ - title: 'Invalid time range', - text: "The provided time range is invalid. (from: 'now', to: 'null')", - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/application/helpers/validate_time_range.ts b/src/plugins/discover_legacy/public/application/helpers/validate_time_range.ts deleted file mode 100644 index d23a84aabb14..000000000000 --- a/src/plugins/discover_legacy/public/application/helpers/validate_time_range.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 dateMath from '@elastic/datemath'; -import { i18n } from '@osd/i18n'; -import { ToastsStart } from 'opensearch-dashboards/public'; - -/** - * Validates a given time filter range, provided by URL or UI - * Unless valid, it returns false and displays a notification - */ -export function validateTimeRange( - { from, to }: { from: string; to: string }, - toastNotifications: ToastsStart -): boolean { - const fromMoment = dateMath.parse(from); - const toMoment = dateMath.parse(to); - if (!fromMoment || !toMoment || !fromMoment.isValid() || !toMoment.isValid()) { - toastNotifications.addDanger({ - title: i18n.translate('discover.notifications.invalidTimeRangeTitle', { - defaultMessage: `Invalid time range`, - }), - text: i18n.translate('discover.notifications.invalidTimeRangeText', { - defaultMessage: `The provided time range is invalid. (from: '{from}', to: '{to}')`, - values: { - from, - to, - }, - }), - }); - return false; - } - return true; -} diff --git a/src/plugins/discover_legacy/public/application/index.scss b/src/plugins/discover_legacy/public/application/index.scss deleted file mode 100644 index b9f191ac6d69..000000000000 --- a/src/plugins/discover_legacy/public/application/index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import "angular/index"; -@import "discover"; diff --git a/src/plugins/discover_legacy/public/build_services.ts b/src/plugins/discover_legacy/public/build_services.ts deleted file mode 100644 index 3fdafcff0c40..000000000000 --- a/src/plugins/discover_legacy/public/build_services.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { History } from 'history'; - -import { - Capabilities, - ChromeStart, - CoreStart, - DocLinksStart, - ToastsStart, - IUiSettingsClient, - PluginInitializerContext, -} from 'opensearch-dashboards/public'; -import { - FilterManager, - TimefilterContract, - IndexPatternsContract, - DataPublicPluginStart, -} from 'src/plugins/data/public'; -import { Start as InspectorPublicPluginStart } from 'src/plugins/inspector/public'; -import { SharePluginStart } from 'src/plugins/share/public'; -import { ChartsPluginStart } from 'src/plugins/charts/public'; -import { VisualizationsStart } from 'src/plugins/visualizations/public'; -import { SavedObjectOpenSearchDashboardsServices } from 'src/plugins/saved_objects/public'; - -import { DiscoverStartPlugins } from './plugin'; -import { createSavedSearchesLoader, SavedSearch } from './saved_searches'; -import { getHistory } from './opensearch_dashboards_services'; -import { OpenSearchDashboardsLegacyStart } from '../../opensearch_dashboards_legacy/public'; -import { UrlForwardingStart } from '../../url_forwarding/public'; -import { NavigationPublicPluginStart } from '../../navigation/public'; - -export interface DiscoverServices { - addBasePath: (path: string) => string; - capabilities: Capabilities; - chrome: ChromeStart; - core: CoreStart; - data: DataPublicPluginStart; - docLinks: DocLinksStart; - history: () => History; - theme: ChartsPluginStart['theme']; - filterManager: FilterManager; - indexPatterns: IndexPatternsContract; - inspector: InspectorPublicPluginStart; - metadata: { branch: string }; - navigation: NavigationPublicPluginStart; - share?: SharePluginStart; - opensearchDashboardsLegacy: OpenSearchDashboardsLegacyStart; - urlForwarding: UrlForwardingStart; - timefilter: TimefilterContract; - toastNotifications: ToastsStart; - getSavedSearchById: (id: string) => Promise; - getSavedSearchUrlById: (id: string) => Promise; - getEmbeddableInjector: any; - uiSettings: IUiSettingsClient; - visualizations: VisualizationsStart; -} - -export async function buildServices( - core: CoreStart, - plugins: DiscoverStartPlugins, - context: PluginInitializerContext, - getEmbeddableInjector: any -): Promise { - const services: SavedObjectOpenSearchDashboardsServices = { - savedObjectsClient: core.savedObjects.client, - indexPatterns: plugins.data.indexPatterns, - search: plugins.data.search, - chrome: core.chrome, - overlays: core.overlays, - }; - const savedObjectService = createSavedSearchesLoader(services); - - return { - addBasePath: core.http.basePath.prepend, - capabilities: core.application.capabilities, - chrome: core.chrome, - core, - data: plugins.data, - docLinks: core.docLinks, - theme: plugins.charts.theme, - filterManager: plugins.data.query.filterManager, - getEmbeddableInjector, - getSavedSearchById: async (id: string) => savedObjectService.get(id), - getSavedSearchUrlById: async (id: string) => savedObjectService.urlFor(id), - history: getHistory, - indexPatterns: plugins.data.indexPatterns, - inspector: plugins.inspector, - metadata: { - branch: context.env.packageInfo.branch, - }, - navigation: plugins.navigation, - share: plugins.share, - opensearchDashboardsLegacy: plugins.opensearchDashboardsLegacy, - urlForwarding: plugins.urlForwarding, - timefilter: plugins.data.query.timefilter.timefilter, - toastNotifications: core.notifications.toasts, - uiSettings: core.uiSettings, - visualizations: plugins.visualizations, - }; -} diff --git a/src/plugins/discover_legacy/public/get_inner_angular.ts b/src/plugins/discover_legacy/public/get_inner_angular.ts deleted file mode 100644 index b4a7a17357ab..000000000000 --- a/src/plugins/discover_legacy/public/get_inner_angular.ts +++ /dev/null @@ -1,208 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -// inner angular imports -// these are necessary to bootstrap the local angular. -// They can stay even after NP cutover -import './application/index.scss'; -import angular from 'angular'; -// required for `ngSanitize` angular module -import 'angular-sanitize'; -import { EuiIcon } from '@elastic/eui'; -import { i18nDirective, i18nFilter, I18nProvider } from '@osd/i18n/angular'; -import { CoreStart, PluginInitializerContext } from 'opensearch-dashboards/public'; -import { DataPublicPluginStart } from '../../data/public'; -import { Storage } from '../../opensearch_dashboards_utils/public'; -import { NavigationPublicPluginStart as NavigationStart } from '../../navigation/public'; -import { createDocTableDirective } from './application/angular/doc_table'; -import { createTableHeaderDirective } from './application/angular/doc_table/components/table_header'; -import { - createToolBarPagerButtonsDirective, - createToolBarPagerTextDirective, -} from './application/angular/doc_table/components/pager'; -import { createTableRowDirective } from './application/angular/doc_table/components/table_row'; -import { createPagerFactory } from './application/angular/doc_table/lib/pager/pager_factory'; -import { createInfiniteScrollDirective } from './application/angular/doc_table/infinite_scroll'; -import { createDocViewerDirective } from './application/angular/doc_viewer'; -import { createDocViewerLinksDirective } from './application/angular/doc_viewer_links'; -import { createRenderCompleteDirective } from './application/angular/directives/render_complete'; -import { - initAngularBootstrap, - configureAppAngularModule, - PrivateProvider, - PromiseServiceCreator, - registerListenEventListener, - watchMultiDecorator, - createTopNavDirective, - createTopNavHelper, -} from '../../opensearch_dashboards_legacy/public'; -import { createContextErrorMessageDirective } from './application/components/context_error_message'; -import { DiscoverStartPlugins } from './plugin'; -import { getScopedHistory } from './opensearch_dashboards_services'; -import { createDiscoverLegacyDirective } from './application/components/create_discover_legacy_directive'; - -/** - * returns the main inner angular module, it contains all the parts of Angular Discover - * needs to render, so in the end the current 'opensearchDashboards' angular module is no longer necessary - */ -export function getInnerAngularModule( - name: string, - core: CoreStart, - deps: DiscoverStartPlugins, - context: PluginInitializerContext -) { - initAngularBootstrap(); - const module = initializeInnerAngularModule(name, core, deps.navigation, deps.data); - configureAppAngularModule(module, { core, env: context.env }, true, getScopedHistory); - return module; -} - -/** - * returns a slimmer inner angular module for embeddable rendering - */ -export function getInnerAngularModuleEmbeddable( - name: string, - core: CoreStart, - deps: DiscoverStartPlugins -) { - return initializeInnerAngularModule(name, core, deps.navigation, deps.data, true); -} - -let initialized = false; - -export function initializeInnerAngularModule( - name = 'app/discover', - core: CoreStart, - navigation: NavigationStart, - data: DataPublicPluginStart, - embeddable = false -) { - if (!initialized) { - createLocalI18nModule(); - createLocalPrivateModule(); - createLocalPromiseModule(); - createLocalTopNavModule(navigation); - createLocalStorageModule(); - createPagerFactoryModule(); - createDocTableModule(); - initialized = true; - } - - if (embeddable) { - return angular - .module(name, [ - 'ngSanitize', - 'react', - 'ui.bootstrap', - 'discoverI18n', - 'discoverPrivate', - 'discoverDocTable', - 'discoverPagerFactory', - 'discoverPromise', - ]) - .config(watchMultiDecorator) - .directive('icon', (reactDirective) => reactDirective(EuiIcon)) - .directive('renderComplete', createRenderCompleteDirective); - } - - return angular - .module(name, [ - 'ngSanitize', - 'ngRoute', - 'react', - 'ui.bootstrap', - 'discoverI18n', - 'discoverPrivate', - 'discoverPromise', - 'discoverTopNav', - 'discoverLocalStorageProvider', - 'discoverDocTable', - 'discoverPagerFactory', - ]) - .config(watchMultiDecorator) - .run(registerListenEventListener) - .directive('icon', (reactDirective) => reactDirective(EuiIcon)) - .directive('renderComplete', createRenderCompleteDirective) - .directive('discoverLegacy', createDiscoverLegacyDirective) - .directive('contextErrorMessage', createContextErrorMessageDirective); -} - -function createLocalPromiseModule() { - angular.module('discoverPromise', []).service('Promise', PromiseServiceCreator); -} - -function createLocalPrivateModule() { - angular.module('discoverPrivate', []).provider('Private', PrivateProvider); -} - -function createLocalTopNavModule(navigation: NavigationStart) { - angular - .module('discoverTopNav', ['react']) - .directive('osdTopNav', createTopNavDirective) - .directive('osdTopNavHelper', createTopNavHelper(navigation.ui)); -} - -function createLocalI18nModule() { - angular - .module('discoverI18n', []) - .provider('i18n', I18nProvider) - .filter('i18n', i18nFilter) - .directive('i18nId', i18nDirective); -} - -function createLocalStorageModule() { - angular - .module('discoverLocalStorageProvider', ['discoverPrivate']) - .service('localStorage', createLocalStorageService('localStorage')) - .service('sessionStorage', createLocalStorageService('sessionStorage')); -} - -const createLocalStorageService = function (type: string) { - return function ($window: any) { - return new Storage($window[type]); - }; -}; - -function createPagerFactoryModule() { - angular.module('discoverPagerFactory', []).factory('pagerFactory', createPagerFactory); -} - -function createDocTableModule() { - angular - .module('discoverDocTable', ['discoverPagerFactory', 'react']) - .directive('docTable', createDocTableDirective) - .directive('osdTableHeader', createTableHeaderDirective) - .directive('toolBarPagerText', createToolBarPagerTextDirective) - .directive('osdTableRow', createTableRowDirective) - .directive('toolBarPagerButtons', createToolBarPagerButtonsDirective) - .directive('osdInfiniteScroll', createInfiniteScrollDirective) - .directive('docViewer', createDocViewerDirective) - .directive('docViewerLinks', createDocViewerLinksDirective); -} diff --git a/src/plugins/discover_legacy/public/index.ts b/src/plugins/discover_legacy/public/index.ts deleted file mode 100644 index 6c9ab46b656e..000000000000 --- a/src/plugins/discover_legacy/public/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { PluginInitializerContext } from 'opensearch-dashboards/public'; -import { DiscoverPlugin } from './plugin'; - -export { DiscoverSetup, DiscoverStart } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { - return new DiscoverPlugin(initializerContext); -} - -export { SavedSearch, SavedSearchLoader, createSavedSearchesLoader } from './saved_searches'; -export { ISearchEmbeddable, SEARCH_EMBEDDABLE_TYPE, SearchInput } from './application/embeddable'; -export { DISCOVER_APP_URL_GENERATOR, DiscoverUrlGeneratorState } from './url_generator'; diff --git a/src/plugins/discover_legacy/public/mocks.ts b/src/plugins/discover_legacy/public/mocks.ts deleted file mode 100644 index 4724ced290ff..000000000000 --- a/src/plugins/discover_legacy/public/mocks.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { DiscoverSetup, DiscoverStart } from '.'; - -export type Setup = jest.Mocked; -export type Start = jest.Mocked; - -const createSetupContract = (): Setup => { - const setupContract: Setup = { - docViews: { - addDocView: jest.fn(), - }, - docViewsLinks: { - addDocViewLink: jest.fn(), - }, - }; - return setupContract; -}; - -const createStartContract = (): Start => { - const startContract: Start = { - savedSearchLoader: {} as any, - urlGenerator: { - createUrl: jest.fn(), - } as any, - }; - return startContract; -}; - -export const discoverPluginMock = { - createSetupContract, - createStartContract, -}; diff --git a/src/plugins/discover_legacy/public/opensearch_dashboards_services.ts b/src/plugins/discover_legacy/public/opensearch_dashboards_services.ts deleted file mode 100644 index 8531564e0cc7..000000000000 --- a/src/plugins/discover_legacy/public/opensearch_dashboards_services.ts +++ /dev/null @@ -1,129 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; -import { createHashHistory } from 'history'; -import { ScopedHistory, AppMountParameters } from 'opensearch-dashboards/public'; -import { UiActionsStart } from 'src/plugins/ui_actions/public'; -import { DiscoverServices } from './build_services'; -import { createGetterSetter } from '../../opensearch_dashboards_utils/public'; -import { search } from '../../data/public'; -import { DocViewsRegistry } from './application/doc_views/doc_views_registry'; -import { DocViewsLinksRegistry } from './application/doc_views_links/doc_views_links_registry'; - -let angularModule: any = null; -let services: DiscoverServices | null = null; -let uiActions: UiActionsStart; - -/** - * set bootstrapped inner angular module - */ -export function setAngularModule(module: any) { - angularModule = module; -} - -/** - * get boostrapped inner angular module - */ -export function getAngularModule() { - return angularModule; -} - -export function getServices(): DiscoverServices { - if (!services) { - throw new Error('Discover services are not yet available'); - } - return services; -} - -export function setServices(newServices: any) { - services = newServices; -} - -export const setUiActions = (pluginUiActions: UiActionsStart) => (uiActions = pluginUiActions); -export const getUiActions = () => uiActions; - -export const [getHeaderActionMenuMounter, setHeaderActionMenuMounter] = createGetterSetter< - AppMountParameters['setHeaderActionMenu'] ->('headerActionMenuMounter'); - -export const [getUrlTracker, setUrlTracker] = createGetterSetter<{ - setTrackedUrl: (url: string) => void; - restorePreviousUrl: () => void; -}>('urlTracker'); - -export const [getDocViewsRegistry, setDocViewsRegistry] = createGetterSetter( - 'DocViewsRegistry' -); - -export const [getDocViewsLinksRegistry, setDocViewsLinksRegistry] = createGetterSetter< - DocViewsLinksRegistry ->('DocViewsLinksRegistry'); -/** - * Makes sure discover and context are using one instance of history. - */ -export const getHistory = _.once(() => createHashHistory()); - -/** - * Discover currently uses two `history` instances: one from OpenSearch Dashboards Platform and - * another from `history` package. Below function is used every time Discover - * app is loaded to synchronize both instances. - * - * This helper is temporary until https://github.com/elastic/kibana/issues/65161 is resolved. - */ -export const syncHistoryLocations = () => { - const h = getHistory(); - Object.assign(h.location, createHashHistory().location); - return h; -}; - -export const [getScopedHistory, setScopedHistory] = createGetterSetter( - 'scopedHistory' -); - -export const { getRequestInspectorStats, getResponseInspectorStats, tabifyAggResponse } = search; -export { unhashUrl, redirectWhenMissing } from '../../opensearch_dashboards_utils/public'; -export { - formatMsg, - formatStack, - subscribeWithScope, -} from '../../opensearch_dashboards_legacy/public'; - -// EXPORT types -export { - IndexPatternsContract, - IIndexPattern, - IndexPattern, - indexPatterns, - IFieldType, - ISearchSource, - OpenSearchQuerySortValue, - SortDirection, -} from '../../data/public'; diff --git a/src/plugins/discover_legacy/public/plugin.ts b/src/plugins/discover_legacy/public/plugin.ts deleted file mode 100644 index 7e855b707891..000000000000 --- a/src/plugins/discover_legacy/public/plugin.ts +++ /dev/null @@ -1,487 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { i18n } from '@osd/i18n'; -import angular, { auto } from 'angular'; -import { BehaviorSubject } from 'rxjs'; -import { filter, map } from 'rxjs/operators'; - -import { - AppMountParameters, - AppUpdater, - CoreSetup, - CoreStart, - Plugin, - PluginInitializerContext, -} from 'opensearch-dashboards/public'; -import { UiActionsStart, UiActionsSetup } from 'src/plugins/ui_actions/public'; -import { EmbeddableStart, EmbeddableSetup } from 'src/plugins/embeddable/public'; -import { ChartsPluginStart } from 'src/plugins/charts/public'; -import { NavigationPublicPluginStart as NavigationStart } from 'src/plugins/navigation/public'; -import { SharePluginStart, SharePluginSetup, UrlGeneratorContract } from 'src/plugins/share/public'; -import { VisualizationsStart, VisualizationsSetup } from 'src/plugins/visualizations/public'; -import { - OpenSearchDashboardsLegacySetup, - OpenSearchDashboardsLegacyStart, -} from 'src/plugins/opensearch_dashboards_legacy/public'; -import { UrlForwardingSetup, UrlForwardingStart } from 'src/plugins/url_forwarding/public'; -import { HomePublicPluginSetup } from 'src/plugins/home/public'; -import { Start as InspectorPublicPluginStart } from 'src/plugins/inspector/public'; -import { stringify } from 'query-string'; -import rison from 'rison-node'; -import { NEW_DISCOVER_APP } from '../../discover/public'; -import { DataPublicPluginStart, DataPublicPluginSetup, opensearchFilters } from '../../data/public'; -import { SavedObjectLoader } from '../../saved_objects/public'; -import { createOsdUrlTracker, url } from '../../opensearch_dashboards_utils/public'; -import { UrlGeneratorState } from '../../share/public'; -import { DocViewInput, DocViewInputFn } from './application/doc_views/doc_views_types'; -import { DocViewLink } from './application/doc_views_links/doc_views_links_types'; -import { DocViewsRegistry } from './application/doc_views/doc_views_registry'; -import { DocViewsLinksRegistry } from './application/doc_views_links/doc_views_links_registry'; -import { DocViewTable } from './application/components/table/table'; -import { JsonCodeBlock } from './application/components/json_code_block/json_code_block'; -import { - setDocViewsRegistry, - setDocViewsLinksRegistry, - setUrlTracker, - setAngularModule, - setServices, - setHeaderActionMenuMounter, - setUiActions, - setScopedHistory, - getScopedHistory, - syncHistoryLocations, - getServices, -} from './opensearch_dashboards_services'; -import { createSavedSearchesLoader } from './saved_searches'; -import { buildServices } from './build_services'; -import { - DiscoverUrlGeneratorState, - DISCOVER_APP_URL_GENERATOR, - DiscoverUrlGenerator, -} from './url_generator'; -import { SearchEmbeddableFactory } from './application/embeddable'; -import { AppNavLinkStatus } from '../../../core/public'; -import { ViewRedirectParams } from '../../data_explorer/public'; - -declare module '../../share/public' { - export interface UrlGeneratorStateMapping { - [DISCOVER_APP_URL_GENERATOR]: UrlGeneratorState; - } -} - -/** - * @public - */ -export interface DiscoverSetup { - docViews: { - /** - * Add new doc view shown along with table view and json view in the details of each document in Discover. - * Both react and angular doc views are supported. - * @param docViewRaw - */ - addDocView(docViewRaw: DocViewInput | DocViewInputFn): void; - }; - - docViewsLinks: { - addDocViewLink(docViewLinkRaw: DocViewLink): void; - }; -} - -export interface DiscoverStart { - savedSearchLoader: SavedObjectLoader; - - /** - * `share` plugin URL generator for Discover app. Use it to generate links into - * Discover application, example: - * - * ```ts - * const url = await plugins.discover.urlGenerator.createUrl({ - * savedSearchId: '571aaf70-4c88-11e8-b3d7-01146121b73d', - * indexPatternId: 'c367b774-a4c2-11ea-bb37-0242ac130002', - * timeRange: { - * to: 'now', - * from: 'now-15m', - * mode: 'relative', - * }, - * }); - * ``` - */ - readonly urlGenerator: undefined | UrlGeneratorContract<'DISCOVER_APP_URL_GENERATOR'>; -} - -/** - * @internal - */ -export interface DiscoverSetupPlugins { - share?: SharePluginSetup; - uiActions: UiActionsSetup; - embeddable: EmbeddableSetup; - opensearchDashboardsLegacy: OpenSearchDashboardsLegacySetup; - urlForwarding: UrlForwardingSetup; - home?: HomePublicPluginSetup; - visualizations: VisualizationsSetup; - data: DataPublicPluginSetup; -} - -/** - * @internal - */ -export interface DiscoverStartPlugins { - uiActions: UiActionsStart; - embeddable: EmbeddableStart; - navigation: NavigationStart; - charts: ChartsPluginStart; - data: DataPublicPluginStart; - share?: SharePluginStart; - opensearchDashboardsLegacy: OpenSearchDashboardsLegacyStart; - urlForwarding: UrlForwardingStart; - inspector: InspectorPublicPluginStart; - visualizations: VisualizationsStart; -} - -const innerAngularName = 'app/discover'; -const embeddableAngularName = 'app/discoverEmbeddable'; - -/** - * Contains Discover, one of the oldest parts of OpenSearch Dashboards - * There are 2 kinds of Angular bootstrapped for rendering, additionally to the main Angular - * Discover provides embeddables, those contain a slimmer Angular - */ -export class DiscoverPlugin - implements Plugin { - constructor(private readonly initializerContext: PluginInitializerContext) {} - - private appStateUpdater = new BehaviorSubject(() => ({})); - private docViewsRegistry: DocViewsRegistry | null = null; - private docViewsLinksRegistry: DocViewsLinksRegistry | null = null; - private embeddableInjector: auto.IInjectorService | null = null; - private stopUrlTracking: (() => void) | undefined = undefined; - private servicesInitialized: boolean = false; - private innerAngularInitialized: boolean = false; - private urlGenerator?: DiscoverStart['urlGenerator']; - - /** - * why are those functions public? they are needed for some mocha tests - * can be removed once all is Jest - */ - public initializeInnerAngular?: () => void; - public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>; - - setup(core: CoreSetup, plugins: DiscoverSetupPlugins) { - const baseUrl = core.http.basePath.prepend('/app/discover'); - - if (plugins.share) { - this.urlGenerator = plugins.share.urlGenerators.registerUrlGenerator( - new DiscoverUrlGenerator({ - appBasePath: baseUrl, - useHash: core.uiSettings.get('state:storeInSessionStorage'), - }) - ); - } - - this.docViewsRegistry = new DocViewsRegistry(); - setDocViewsRegistry(this.docViewsRegistry); - this.docViewsRegistry.addDocView({ - title: i18n.translate('discover.docViews.table.tableTitle', { - defaultMessage: 'Table', - }), - order: 10, - component: DocViewTable, - }); - - this.docViewsRegistry.addDocView({ - title: i18n.translate('discover.docViews.json.jsonTitle', { - defaultMessage: 'JSON', - }), - order: 20, - component: JsonCodeBlock, - }); - - this.docViewsLinksRegistry = new DocViewsLinksRegistry(); - setDocViewsLinksRegistry(this.docViewsLinksRegistry); - - this.docViewsLinksRegistry.addDocViewLink({ - label: i18n.translate('discover.docTable.tableRow.viewSurroundingDocumentsLinkText', { - defaultMessage: 'View surrounding documents', - }), - generateCb: (renderProps: any) => { - const globalFilters: any = getServices().filterManager.getGlobalFilters(); - const appFilters: any = getServices().filterManager.getAppFilters(); - - const hash = stringify( - url.encodeQuery({ - _g: rison.encode({ - filters: globalFilters || [], - }), - _a: rison.encode({ - columns: renderProps.columns, - filters: (appFilters || []).map(opensearchFilters.disableFilter), - }), - }), - { encode: false, sort: false } - ); - - return { - url: `#/context/${encodeURIComponent(renderProps.indexPattern.id)}/${encodeURIComponent( - renderProps.hit._id - )}?${hash}`, - hide: !renderProps.indexPattern.isTimeBased(), - }; - }, - order: 1, - }); - - this.docViewsLinksRegistry.addDocViewLink({ - label: i18n.translate('discover.docTable.tableRow.viewSingleDocumentLinkText', { - defaultMessage: 'View single document', - }), - generateCb: (renderProps) => ({ - url: `#/doc/${renderProps.indexPattern.id}/${ - renderProps.hit._index - }?id=${encodeURIComponent(renderProps.hit._id)}`, - }), - order: 2, - }); - - const { - appMounted, - appUnMounted, - stop: stopUrlTracker, - setActiveUrl: setTrackedUrl, - restorePreviousUrl, - } = createOsdUrlTracker({ - // we pass getter here instead of plain `history`, - // so history is lazily created (when app is mounted) - // this prevents redundant `#` when not in discover app - getHistory: getScopedHistory, - baseUrl, - defaultSubUrl: '#/', - storageKey: `lastUrl:${core.http.basePath.get()}:discover_legacy`, - navLinkUpdater$: this.appStateUpdater, - toastNotifications: core.notifications.toasts, - stateParams: [ - { - osdUrlKey: '_g', - stateUpdate$: plugins.data.query.state$.pipe( - filter( - ({ changes }) => !!(changes.globalFilters || changes.time || changes.refreshInterval) - ), - map(({ state }) => ({ - ...state, - filters: state.filters?.filter(opensearchFilters.isFilterPinned), - })) - ), - }, - ], - }); - setUrlTracker({ setTrackedUrl, restorePreviousUrl }); - this.stopUrlTracking = () => { - stopUrlTracker(); - }; - - this.docViewsRegistry.setAngularInjectorGetter(this.getEmbeddableInjector); - core.application.register({ - id: 'discoverLegacy', - title: 'Discover Legacy', - defaultPath: '#/', - navLinkStatus: AppNavLinkStatus.hidden, - mount: async (params: AppMountParameters) => { - if (!this.initializeServices) { - throw Error('Discover plugin method initializeServices is undefined'); - } - if (!this.initializeInnerAngular) { - throw Error('Discover plugin method initializeInnerAngular is undefined'); - } - - // If a user explicitly tries to access the legacy app URL - const { - core: { - application: { navigateToApp }, - }, - } = await this.initializeServices(); - const path = window.location.hash; - - const v2Enabled = core.uiSettings.get(NEW_DISCOVER_APP); - if (v2Enabled) { - navigateToApp('discover', { - replace: true, - path, - }); - } - setScopedHistory(params.history); - setHeaderActionMenuMounter(params.setHeaderActionMenu); - syncHistoryLocations(); - appMounted(); - const { - plugins: { data: dataStart }, - } = await this.initializeServices(); - await this.initializeInnerAngular(); - - // make sure the index pattern list is up to date - await dataStart.indexPatterns.clearCache(); - const { renderApp } = await import('./application/application'); - params.element.classList.add('dscAppWrapper'); - const unmount = await renderApp(innerAngularName, params.element); - return () => { - params.element.classList.remove('dscAppWrapper'); - unmount(); - appUnMounted(); - }; - }, - }); - - plugins.urlForwarding.forwardApp('doc', 'discoverLegacy', (path) => { - return `#${path}`; - }); - plugins.urlForwarding.forwardApp('context', 'discoverLegacy', (path) => { - const urlParts = path.split('/'); - // take care of urls containing legacy url, those split in the following way - // ["", "context", indexPatternId, _type, id + params] - if (urlParts[4]) { - // remove _type part - const newPath = [...urlParts.slice(0, 3), ...urlParts.slice(4)].join('/'); - return `#${newPath}`; - } - return `#${path}`; - }); - plugins.urlForwarding.forwardApp('discover', 'discoverLegacy', (path) => { - const [, id, tail] = /discover\/([^\?]+)(.*)/.exec(path) || []; - if (!id) { - return `#${path.replace('/discover', '') || '/'}`; - } - return `#/view/${id}${tail || ''}`; - }); - - this.registerEmbeddable(core, plugins); - - return { - docViews: { - addDocView: this.docViewsRegistry.addDocView.bind(this.docViewsRegistry), - }, - docViewsLinks: { - addDocViewLink: this.docViewsLinksRegistry.addDocViewLink.bind(this.docViewsLinksRegistry), - }, - }; - } - - start(core: CoreStart, plugins: DiscoverStartPlugins) { - // we need to register the application service at setup, but to render it - // there are some start dependencies necessary, for this reason - // initializeInnerAngular + initializeServices are assigned at start and used - // when the application/embeddable is mounted - this.initializeInnerAngular = async () => { - if (this.innerAngularInitialized) { - return; - } - // this is used by application mount and tests - const { getInnerAngularModule } = await import('./get_inner_angular'); - const module = getInnerAngularModule( - innerAngularName, - core, - plugins, - this.initializerContext - ); - setAngularModule(module); - this.innerAngularInitialized = true; - }; - - setUiActions(plugins.uiActions); - - this.initializeServices = async () => { - if (this.servicesInitialized) { - return { core, plugins }; - } - const services = await buildServices( - core, - plugins, - this.initializerContext, - this.getEmbeddableInjector - ); - setServices(services); - this.servicesInitialized = true; - - return { core, plugins }; - }; - - return { - urlGenerator: this.urlGenerator, - savedSearchLoader: createSavedSearchesLoader({ - savedObjectsClient: core.savedObjects.client, - indexPatterns: plugins.data.indexPatterns, - search: plugins.data.search, - chrome: core.chrome, - overlays: core.overlays, - }), - }; - } - - stop() { - if (this.stopUrlTracking) { - this.stopUrlTracking(); - } - } - - /** - * register embeddable with a slimmer embeddable version of inner angular - */ - private registerEmbeddable(core: CoreSetup, plugins: DiscoverSetupPlugins) { - if (!this.getEmbeddableInjector) { - throw Error('Discover plugin method getEmbeddableInjector is undefined'); - } - - const getStartServices = async () => { - const [coreStart, deps] = await core.getStartServices(); - return { - executeTriggerActions: deps.uiActions.executeTriggerActions, - isEditable: () => coreStart.application.capabilities.discover.save as boolean, - }; - }; - - const factory = new SearchEmbeddableFactory(getStartServices, this.getEmbeddableInjector); - plugins.embeddable.registerEmbeddableFactory(factory.type, factory); - } - - private getEmbeddableInjector = async () => { - if (!this.embeddableInjector) { - if (!this.initializeServices) { - throw Error('Discover plugin getEmbeddableInjector: initializeServices is undefined'); - } - const { core, plugins } = await this.initializeServices(); - getServices().opensearchDashboardsLegacy.loadFontAwesome(); - const { getInnerAngularModuleEmbeddable } = await import('./get_inner_angular'); - getInnerAngularModuleEmbeddable(embeddableAngularName, core, plugins); - const mountpoint = document.createElement('div'); - this.embeddableInjector = angular.bootstrap(mountpoint, [embeddableAngularName]); - } - - return this.embeddableInjector; - }; -} diff --git a/src/plugins/discover_legacy/public/saved_searches/_saved_search.ts b/src/plugins/discover_legacy/public/saved_searches/_saved_search.ts deleted file mode 100644 index 55cd59104ecb..000000000000 --- a/src/plugins/discover_legacy/public/saved_searches/_saved_search.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { - createSavedObjectClass, - SavedObject, - SavedObjectOpenSearchDashboardsServices, -} from '../../../saved_objects/public'; - -export function createSavedSearchClass(services: SavedObjectOpenSearchDashboardsServices) { - const SavedObjectClass = createSavedObjectClass(services); - - class SavedSearch extends SavedObjectClass { - public static type: string = 'search'; - public static mapping = { - title: 'text', - description: 'text', - hits: 'integer', - columns: 'keyword', - sort: 'keyword', - version: 'integer', - }; - // Order these fields to the top, the rest are alphabetical - public static fieldOrder = ['title', 'description']; - public static searchSource = true; - - public id: string; - public showInRecentlyAccessed: boolean; - - constructor(id: string) { - super({ - id, - type: 'search', - mapping: { - title: 'text', - description: 'text', - hits: 'integer', - columns: 'keyword', - sort: 'keyword', - version: 'integer', - }, - searchSource: true, - defaults: { - title: '', - description: '', - columns: [], - hits: 0, - sort: [], - version: 1, - }, - }); - this.showInRecentlyAccessed = true; - this.id = id; - this.getFullPath = () => `/app/discover#/view/${String(id)}`; - } - } - - return SavedSearch as new (id: string) => SavedObject; -} diff --git a/src/plugins/discover_legacy/public/saved_searches/index.ts b/src/plugins/discover_legacy/public/saved_searches/index.ts deleted file mode 100644 index f576a9a9377a..000000000000 --- a/src/plugins/discover_legacy/public/saved_searches/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { createSavedSearchesLoader } from './saved_searches'; -export { SavedSearch, SavedSearchLoader } from './types'; diff --git a/src/plugins/discover_legacy/public/saved_searches/saved_searches.ts b/src/plugins/discover_legacy/public/saved_searches/saved_searches.ts deleted file mode 100644 index dd3243568159..000000000000 --- a/src/plugins/discover_legacy/public/saved_searches/saved_searches.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { - SavedObjectLoader, - SavedObjectOpenSearchDashboardsServices, -} from '../../../saved_objects/public'; -import { createSavedSearchClass } from './_saved_search'; - -export function createSavedSearchesLoader(services: SavedObjectOpenSearchDashboardsServices) { - const SavedSearchClass = createSavedSearchClass(services); - const savedSearchLoader = new SavedObjectLoader(SavedSearchClass, services.savedObjectsClient); - // Customize loader properties since adding an 's' on type doesn't work for type 'search' . - savedSearchLoader.loaderProperties = { - name: 'searches', - noun: 'Saved Search', - nouns: 'saved searches', - }; - - savedSearchLoader.urlFor = (id: string) => (id ? `#/view/${encodeURIComponent(id)}` : '#/'); - - return savedSearchLoader; -} diff --git a/src/plugins/discover_legacy/public/saved_searches/types.ts b/src/plugins/discover_legacy/public/saved_searches/types.ts deleted file mode 100644 index e02fd65e6899..000000000000 --- a/src/plugins/discover_legacy/public/saved_searches/types.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { ISearchSource } from '../../../data/public'; - -export type SortOrder = [string, string]; -export interface SavedSearch { - readonly id: string; - title: string; - searchSource: ISearchSource; - description?: string; - columns: string[]; - sort: SortOrder[]; - destroy: () => void; - lastSavedTitle?: string; -} -export interface SavedSearchLoader { - get: (id: string) => Promise; - urlFor: (id: string) => string; -} diff --git a/src/plugins/discover_legacy/public/url_generator.test.ts b/src/plugins/discover_legacy/public/url_generator.test.ts deleted file mode 100644 index c352dd5133a4..000000000000 --- a/src/plugins/discover_legacy/public/url_generator.test.ts +++ /dev/null @@ -1,269 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { DiscoverUrlGenerator } from './url_generator'; -import { hashedItemStore, getStatesFromOsdUrl } from '../../opensearch_dashboards_utils/public'; -import { mockStorage } from '../../opensearch_dashboards_utils/public/storage/hashed_item_store/mock'; -import { FilterStateStore } from '../../data/common'; - -const appBasePath: string = 'xyz/app/discover'; -const indexPatternId: string = 'c367b774-a4c2-11ea-bb37-0242ac130002'; -const savedSearchId: string = '571aaf70-4c88-11e8-b3d7-01146121b73d'; - -interface SetupParams { - useHash?: boolean; -} - -const setup = async ({ useHash = false }: SetupParams = {}) => { - const generator = new DiscoverUrlGenerator({ - appBasePath, - useHash, - }); - - return { - generator, - }; -}; - -beforeEach(() => { - // @ts-ignore - hashedItemStore.storage = mockStorage; -}); - -describe('Discover url generator', () => { - test('can create a link to Discover with no state and no saved search', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({}); - const { _a, _g } = getStatesFromOsdUrl(url, ['_a', '_g']); - - expect(url.startsWith(appBasePath)).toBe(true); - expect(_a).toEqual({}); - expect(_g).toEqual({}); - }); - - test('can create a link to a saved search in Discover', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ savedSearchId }); - const { _a, _g } = getStatesFromOsdUrl(url, ['_a', '_g']); - - expect(url.startsWith(`${appBasePath}#/${savedSearchId}`)).toBe(true); - expect(_a).toEqual({}); - expect(_g).toEqual({}); - }); - - test('can specify specific index pattern', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - indexPatternId, - }); - const { _a, _g } = getStatesFromOsdUrl(url, ['_a', '_g']); - - expect(_a).toEqual({ - index: indexPatternId, - }); - expect(_g).toEqual({}); - }); - - test('can specify specific time range', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - timeRange: { to: 'now', from: 'now-15m', mode: 'relative' }, - }); - const { _a, _g } = getStatesFromOsdUrl(url, ['_a', '_g']); - - expect(_a).toEqual({}); - expect(_g).toEqual({ - time: { - from: 'now-15m', - mode: 'relative', - to: 'now', - }, - }); - }); - - test('can specify query', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - query: { - language: 'kuery', - query: 'foo', - }, - }); - const { _a, _g } = getStatesFromOsdUrl(url, ['_a', '_g']); - - expect(_a).toEqual({ - query: { - language: 'kuery', - query: 'foo', - }, - }); - expect(_g).toEqual({}); - }); - - test('can specify local and global filters', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - filters: [ - { - meta: { - alias: 'foo', - disabled: false, - negate: false, - }, - $state: { - store: FilterStateStore.APP_STATE, - }, - }, - { - meta: { - alias: 'bar', - disabled: false, - negate: false, - }, - $state: { - store: FilterStateStore.GLOBAL_STATE, - }, - }, - ], - }); - const { _a, _g } = getStatesFromOsdUrl(url, ['_a', '_g']); - - expect(_a).toEqual({ - filters: [ - { - $state: { - store: 'appState', - }, - meta: { - alias: 'foo', - disabled: false, - negate: false, - }, - }, - ], - }); - expect(_g).toEqual({ - filters: [ - { - $state: { - store: 'globalState', - }, - meta: { - alias: 'bar', - disabled: false, - negate: false, - }, - }, - ], - }); - }); - - test('can set refresh interval', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - refreshInterval: { - pause: false, - value: 666, - }, - }); - const { _a, _g } = getStatesFromOsdUrl(url, ['_a', '_g']); - - expect(_a).toEqual({}); - expect(_g).toEqual({ - refreshInterval: { - pause: false, - value: 666, - }, - }); - }); - - test('can set time range', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - timeRange: { - from: 'now-3h', - to: 'now', - }, - }); - const { _a, _g } = getStatesFromOsdUrl(url, ['_a', '_g']); - - expect(_a).toEqual({}); - expect(_g).toEqual({ - time: { - from: 'now-3h', - to: 'now', - }, - }); - }); - - describe('useHash property', () => { - describe('when default useHash is set to false', () => { - test('when using default, sets index pattern ID in the generated URL', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - indexPatternId, - }); - - expect(url.indexOf(indexPatternId) > -1).toBe(true); - }); - - test('when enabling useHash, does not set index pattern ID in the generated URL', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - useHash: true, - indexPatternId, - }); - - expect(url.indexOf(indexPatternId) > -1).toBe(false); - }); - }); - - describe('when default useHash is set to true', () => { - test('when using default, does not set index pattern ID in the generated URL', async () => { - const { generator } = await setup({ useHash: true }); - const url = await generator.createUrl({ - indexPatternId, - }); - - expect(url.indexOf(indexPatternId) > -1).toBe(false); - }); - - test('when disabling useHash, sets index pattern ID in the generated URL', async () => { - const { generator } = await setup(); - const url = await generator.createUrl({ - useHash: false, - indexPatternId, - }); - - expect(url.indexOf(indexPatternId) > -1).toBe(true); - }); - }); - }); -}); diff --git a/src/plugins/discover_legacy/public/url_generator.ts b/src/plugins/discover_legacy/public/url_generator.ts deleted file mode 100644 index 25e8517c8c9d..000000000000 --- a/src/plugins/discover_legacy/public/url_generator.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { - TimeRange, - Filter, - Query, - opensearchFilters, - QueryState, - RefreshInterval, -} from '../../data/public'; -import { setStateToOsdUrl } from '../../opensearch_dashboards_utils/public'; -import { UrlGeneratorsDefinition } from '../../share/public'; - -export const DISCOVER_APP_URL_GENERATOR = 'DISCOVER_APP_URL_GENERATOR'; - -export interface DiscoverUrlGeneratorState { - /** - * Optionally set saved search ID. - */ - savedSearchId?: string; - - /** - * Optionally set index pattern ID. - */ - indexPatternId?: string; - - /** - * Optionally set the time range in the time picker. - */ - timeRange?: TimeRange; - - /** - * Optionally set the refresh interval. - */ - refreshInterval?: RefreshInterval; - - /** - * Optionally apply filers. - */ - filters?: Filter[]; - - /** - * Optionally set a query. NOTE: if given and used in conjunction with `dashboardId`, and the - * saved dashboard has a query saved with it, this will _replace_ that query. - */ - query?: Query; - - /** - * If not given, will use the uiSettings configuration for `storeInSessionStorage`. useHash determines - * whether to hash the data in the url to avoid url length issues. - */ - useHash?: boolean; -} - -interface Params { - appBasePath: string; - useHash: boolean; -} - -export class DiscoverUrlGenerator - implements UrlGeneratorsDefinition { - constructor(private readonly params: Params) {} - - public readonly id = DISCOVER_APP_URL_GENERATOR; - - public readonly createUrl = async ({ - filters, - indexPatternId, - query, - refreshInterval, - savedSearchId, - timeRange, - useHash = this.params.useHash, - }: DiscoverUrlGeneratorState): Promise => { - const savedSearchPath = savedSearchId ? encodeURIComponent(savedSearchId) : ''; - const appState: { - query?: Query; - filters?: Filter[]; - index?: string; - } = {}; - const queryState: QueryState = {}; - - if (query) appState.query = query; - if (filters && filters.length) - appState.filters = filters?.filter((f) => !opensearchFilters.isFilterPinned(f)); - if (indexPatternId) appState.index = indexPatternId; - - if (timeRange) queryState.time = timeRange; - if (filters && filters.length) - queryState.filters = filters?.filter((f) => opensearchFilters.isFilterPinned(f)); - if (refreshInterval) queryState.refreshInterval = refreshInterval; - - let url = `${this.params.appBasePath}#/${savedSearchPath}`; - url = setStateToOsdUrl('_g', queryState, { useHash }, url); - url = setStateToOsdUrl('_a', appState, { useHash }, url); - - return url; - }; -} diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular/angular_config.tsx b/src/plugins/opensearch_dashboards_legacy/public/angular/angular_config.tsx deleted file mode 100644 index fbe36a289d70..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular/angular_config.tsx +++ /dev/null @@ -1,380 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { - ICompileProvider, - IHttpProvider, - IHttpService, - ILocationProvider, - IModule, - IRootScopeService, -} from 'angular'; -import $ from 'jquery'; -import { set } from '@elastic/safer-lodash-set'; -import { get } from 'lodash'; -import * as Rx from 'rxjs'; -import { ChromeBreadcrumb, EnvironmentMode, PackageInfo } from 'opensearch-dashboards/public'; -import { History } from 'history'; - -import { CoreStart } from 'opensearch-dashboards/public'; -import { isSystemApiRequest } from '../utils'; -import { formatAngularHttpError, isAngularHttpError } from '../notify/lib'; - -export interface RouteConfiguration { - controller?: string | ((...args: any[]) => void); - redirectTo?: string; - resolveRedirectTo?: (...args: any[]) => void; - reloadOnSearch?: boolean; - reloadOnUrl?: boolean; - outerAngularWrapperRoute?: boolean; - resolve?: object; - template?: string; - k7Breadcrumbs?: (...args: any[]) => ChromeBreadcrumb[]; - requireUICapability?: string; -} - -/** - * Detects whether a given angular route is a dummy route that doesn't - * require any action. There are two ways this can happen: - * If `outerAngularWrapperRoute` is set on the route config object, - * it means the local application service set up this route on the outer angular - * and the internal routes will handle the hooks. - * - * If angular did not detect a route and it is the local angular, we are currently - * navigating away from a URL controlled by a local angular router and the - * application will get unmounted. In this case the outer router will handle - * the hooks. - * @param $route Injected $route dependency - * @param isLocalAngular Flag whether this is the local angular router - */ -function isDummyRoute($route: any, isLocalAngular: boolean) { - return ( - ($route.current && $route.current.$$route && $route.current.$$route.outerAngularWrapperRoute) || - (!$route.current && isLocalAngular) - ); -} - -export const configureAppAngularModule = ( - angularModule: IModule, - newPlatform: { - core: CoreStart; - readonly env: { - mode: Readonly; - packageInfo: Readonly; - }; - }, - isLocalAngular: boolean, - getHistory?: () => History -) => { - const core = 'core' in newPlatform ? newPlatform.core : newPlatform; - const packageInfo = newPlatform.env.packageInfo; - - angularModule - .value('osdVersion', packageInfo.version) - .value('buildNum', packageInfo.buildNum) - .value('buildSha', packageInfo.buildSha) - .value('opensearchUrl', getOpenSearchUrl(core)) - .value('uiCapabilities', core.application.capabilities) - .config(setupCompileProvider(newPlatform.env.mode.dev)) - .config(setupLocationProvider()) - .config($setupXsrfRequestInterceptor(packageInfo.version)) - .run(capture$httpLoadingCount(core)) - .run(digestOnHashChange(getHistory)) - .run($setupBreadcrumbsAutoClear(core, isLocalAngular)) - .run($setupBadgeAutoClear(core, isLocalAngular)) - .run($setupHelpExtensionAutoClear(core, isLocalAngular)) - .run($setupUICapabilityRedirect(core)); -}; - -const getOpenSearchUrl = (newPlatform: CoreStart) => { - const a = document.createElement('a'); - a.href = newPlatform.http.basePath.prepend('/opensearch'); - const protocolPort = /https/.test(a.protocol) ? 443 : 80; - const port = a.port || protocolPort; - return { - host: a.hostname, - port, - protocol: a.protocol, - pathname: a.pathname, - }; -}; - -const digestOnHashChange = (getHistory?: () => History) => ($rootScope: IRootScopeService) => { - if (!getHistory) return; - const unlisten = getHistory().listen(() => { - // dispatch synthetic hash change event to update hash history objects and angular routing - // this is necessary because hash updates triggered by using popState won't trigger this event naturally. - // this has to happen in the next tick to not change the existing timing of angular digest cycles. - setTimeout(() => { - window.dispatchEvent(new HashChangeEvent('hashchange')); - }, 0); - }); - $rootScope.$on('$destroy', unlisten); -}; - -const setupCompileProvider = (devMode: boolean) => ($compileProvider: ICompileProvider) => { - if (!devMode) { - $compileProvider.debugInfoEnabled(false); - } -}; - -const setupLocationProvider = () => ($locationProvider: ILocationProvider) => { - $locationProvider.html5Mode({ - enabled: false, - requireBase: false, - rewriteLinks: false, - }); - - $locationProvider.hashPrefix(''); -}; - -export const $setupXsrfRequestInterceptor = (version: string) => { - // Configure jQuery prefilter - $.ajaxPrefilter(({ osdXsrfToken = true }: any, originalOptions, jqXHR) => { - if (osdXsrfToken) { - jqXHR.setRequestHeader('osd-xsrf', 'osd-legacy'); - // ToDo: Remove next; `osd-version` incorrectly used for satisfying XSRF protection - jqXHR.setRequestHeader('osd-version', version); - } - }); - - return ($httpProvider: IHttpProvider) => { - // Configure $httpProvider interceptor - $httpProvider.interceptors.push(() => { - return { - request(opts) { - const { osdXsrfToken = true } = opts as any; - if (osdXsrfToken) { - set(opts, ['headers', 'osd-xsrf'], 'osd-legacy'); - // ToDo: Remove next; `osd-version` incorrectly used for satisfying XSRF protection - set(opts, ['headers', 'osd-version'], version); - } - return opts; - }, - }; - }); - }; -}; - -/** - * Injected into angular module by ui/chrome angular integration - * and adds a root-level watcher that will capture the count of - * active $http requests on each digest loop and expose the count to - * the core.loadingCount api - */ -const capture$httpLoadingCount = (newPlatform: CoreStart) => ( - $rootScope: IRootScopeService, - $http: IHttpService -) => { - newPlatform.http.addLoadingCountSource( - new Rx.Observable((observer) => { - const unwatch = $rootScope.$watch(() => { - const reqs = $http.pendingRequests || []; - observer.next(reqs.filter((req) => !isSystemApiRequest(req)).length); - }); - - return unwatch; - }) - ); -}; - -/** - * integrates with angular to automatically redirect to home if required - * capability is not met - */ -const $setupUICapabilityRedirect = (newPlatform: CoreStart) => ( - $rootScope: IRootScopeService, - $injector: any -) => { - const isOpenSearchDashboardsAppRoute = window.location.pathname.endsWith( - '/app/opensearch-dashboards' - ); - // this feature only works within opensearch dashboards app for now after everything is - // switched to the application service, this can be changed to handle all - // apps. - if (!isOpenSearchDashboardsAppRoute) { - return; - } - $rootScope.$on( - '$routeChangeStart', - (event, { $$route: route }: { $$route?: RouteConfiguration } = {}) => { - if (!route || !route.requireUICapability) { - return; - } - - if (!get(newPlatform.application.capabilities, route.requireUICapability)) { - $injector.get('$location').url('/home'); - event.preventDefault(); - } - } - ); -}; - -/** - * internal angular run function that will be called when angular bootstraps and - * lets us integrate with the angular router so that we can automatically clear - * the breadcrumbs if we switch to a OpenSearch Dashboards app that does not use breadcrumbs correctly - */ -const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart, isLocalAngular: boolean) => ( - $rootScope: IRootScopeService, - $injector: any -) => { - // A flag used to determine if we should automatically - // clear the breadcrumbs between angular route changes. - let breadcrumbSetSinceRouteChange = false; - const $route = $injector.has('$route') ? $injector.get('$route') : {}; - - // reset breadcrumbSetSinceRouteChange any time the breadcrumbs change, even - // if it was done directly through the new platform - newPlatform.chrome.getBreadcrumbs$().subscribe({ - next() { - breadcrumbSetSinceRouteChange = true; - }, - }); - - $rootScope.$on('$routeChangeStart', () => { - breadcrumbSetSinceRouteChange = false; - }); - - $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyRoute($route, isLocalAngular)) { - return; - } - const current = $route.current || {}; - - if (breadcrumbSetSinceRouteChange || (current.$$route && current.$$route.redirectTo)) { - return; - } - - const k7BreadcrumbsProvider = current.k7Breadcrumbs; - if (!k7BreadcrumbsProvider) { - newPlatform.chrome.setBreadcrumbs([]); - return; - } - - try { - newPlatform.chrome.setBreadcrumbs($injector.invoke(k7BreadcrumbsProvider)); - } catch (error) { - if (isAngularHttpError(error)) { - error = formatAngularHttpError(error); - } - newPlatform.fatalErrors.add(error, 'location'); - } - }); -}; - -/** - * internal angular run function that will be called when angular bootstraps and - * lets us integrate with the angular router so that we can automatically clear - * the badge if we switch to a OpenSearch Dashboards app that does not use the badge correctly - */ -const $setupBadgeAutoClear = (newPlatform: CoreStart, isLocalAngular: boolean) => ( - $rootScope: IRootScopeService, - $injector: any -) => { - // A flag used to determine if we should automatically - // clear the badge between angular route changes. - let badgeSetSinceRouteChange = false; - const $route = $injector.has('$route') ? $injector.get('$route') : {}; - - $rootScope.$on('$routeChangeStart', () => { - badgeSetSinceRouteChange = false; - }); - - $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyRoute($route, isLocalAngular)) { - return; - } - const current = $route.current || {}; - - if (badgeSetSinceRouteChange || (current.$$route && current.$$route.redirectTo)) { - return; - } - - const badgeProvider = current.badge; - if (!badgeProvider) { - newPlatform.chrome.setBadge(undefined); - return; - } - - try { - newPlatform.chrome.setBadge($injector.invoke(badgeProvider)); - } catch (error) { - if (isAngularHttpError(error)) { - error = formatAngularHttpError(error); - } - newPlatform.fatalErrors.add(error, 'location'); - } - }); -}; - -/** - * internal angular run function that will be called when angular bootstraps and - * lets us integrate with the angular router so that we can automatically clear - * the helpExtension if we switch to a OpenSearch Dashboards app that does not set its own - * helpExtension - */ -const $setupHelpExtensionAutoClear = (newPlatform: CoreStart, isLocalAngular: boolean) => ( - $rootScope: IRootScopeService, - $injector: any -) => { - /** - * reset helpExtensionSetSinceRouteChange any time the helpExtension changes, even - * if it was done directly through the new platform - */ - let helpExtensionSetSinceRouteChange = false; - newPlatform.chrome.getHelpExtension$().subscribe({ - next() { - helpExtensionSetSinceRouteChange = true; - }, - }); - - const $route = $injector.has('$route') ? $injector.get('$route') : {}; - - $rootScope.$on('$routeChangeStart', () => { - if (isDummyRoute($route, isLocalAngular)) { - return; - } - helpExtensionSetSinceRouteChange = false; - }); - - $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyRoute($route, isLocalAngular)) { - return; - } - const current = $route.current || {}; - - if (helpExtensionSetSinceRouteChange || (current.$$route && current.$$route.redirectTo)) { - return; - } - - newPlatform.chrome.setHelpExtension(current.helpExtension); - }); -}; diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular/index.ts b/src/plugins/opensearch_dashboards_legacy/public/angular/index.ts deleted file mode 100644 index c492de510093..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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. - */ - -// @ts-ignore -export { PromiseServiceCreator } from './promises'; -// @ts-ignore -export { watchMultiDecorator } from './watch_multi'; -export * from './angular_config'; -// @ts-ignore -export { createTopNavDirective, createTopNavHelper, loadOsdTopNavDirectives } from './osd_top_nav'; -export { subscribeWithScope } from './subscribe_with_scope'; diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular/osd_top_nav.js b/src/plugins/opensearch_dashboards_legacy/public/angular/osd_top_nav.js deleted file mode 100644 index 11835005b60c..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular/osd_top_nav.js +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 angular from 'angular'; -import 'ngreact'; - -export function createTopNavDirective() { - return { - restrict: 'E', - template: '', - compile: (elem) => { - const child = document.createElement('osd-top-nav-helper'); - - // Copy attributes to the child directive - for (const attr of elem[0].attributes) { - child.setAttribute(attr.name, attr.value); - } - - // Add a special attribute that will change every time that one - // of the config array's disableButton function return value changes. - child.setAttribute('disabled-buttons', 'disabledButtons'); - - // Append helper directive - elem.append(child); - - const linkFn = ($scope, _, $attr) => { - // Watch config changes - $scope.$watch( - () => { - const config = $scope.$eval($attr.config) || []; - return config.map((item) => { - // Copy key into id, as it's a reserved react propery. - // This is done for Angular directive backward compatibility. - // In React only id is recognized. - if (item.key && !item.id) { - item.id = item.key; - } - - // Watch the disableButton functions - if (typeof item.disableButton === 'function') { - return item.disableButton(); - } - return item.disableButton; - }); - }, - (newVal) => { - $scope.disabledButtons = newVal; - }, - true - ); - }; - - return linkFn; - }, - }; -} - -export const createTopNavHelper = ({ TopNavMenu }) => (reactDirective) => { - return reactDirective(TopNavMenu, [ - ['config', { watchDepth: 'value' }], - ['setMenuMountPoint', { watchDepth: 'reference' }], - ['disabledButtons', { watchDepth: 'reference' }], - - ['query', { watchDepth: 'reference' }], - ['savedQuery', { watchDepth: 'reference' }], - ['intl', { watchDepth: 'reference' }], - - ['onQuerySubmit', { watchDepth: 'reference' }], - ['onFiltersUpdated', { watchDepth: 'reference' }], - ['onRefreshChange', { watchDepth: 'reference' }], - ['onClearSavedQuery', { watchDepth: 'reference' }], - ['onSaved', { watchDepth: 'reference' }], - ['onSavedQueryUpdated', { watchDepth: 'reference' }], - ['onSavedQueryIdChange', { watchDepth: 'reference' }], - - ['indexPatterns', { watchDepth: 'collection' }], - ['filters', { watchDepth: 'collection' }], - - // All modifiers default to true. - // Set to false to hide subcomponents. - 'showSearchBar', - 'showQueryBar', - 'showQueryInput', - 'showSaveQuery', - 'showDatePicker', - 'showFilterBar', - - 'appName', - 'screenTitle', - 'dateRangeFrom', - 'dateRangeTo', - 'savedQueryId', - 'isRefreshPaused', - 'refreshInterval', - 'disableAutoFocus', - 'showAutoRefreshOnly', - - // temporary flag to use the stateful components - 'useDefaultBehaviors', - ]); -}; - -let isLoaded = false; - -export function loadOsdTopNavDirectives(navUi) { - if (!isLoaded) { - isLoaded = true; - angular - .module('opensearchDashboards') - .directive('osdTopNav', createTopNavDirective) - .directive('osdTopNavHelper', createTopNavHelper(navUi)); - } -} diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular/promises.js b/src/plugins/opensearch_dashboards_legacy/public/angular/promises.js deleted file mode 100644 index 690bc5489d10..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular/promises.js +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; - -export function PromiseServiceCreator($q, $timeout) { - function Promise(fn) { - if (typeof this === 'undefined') - throw new Error('Promise constructor must be called with "new"'); - - const defer = $q.defer(); - try { - fn(defer.resolve, defer.reject); - } catch (e) { - defer.reject(e); - } - return defer.promise; - } - - Promise.all = Promise.props = $q.all; - Promise.resolve = function (val) { - const defer = $q.defer(); - defer.resolve(val); - return defer.promise; - }; - Promise.reject = function (reason) { - const defer = $q.defer(); - defer.reject(reason); - return defer.promise; - }; - Promise.cast = $q.when; - Promise.delay = function (ms) { - return $timeout(_.noop, ms); - }; - Promise.method = function (fn) { - return function () { - const args = Array.prototype.slice.call(arguments); - return Promise.try(fn, args, this); - }; - }; - Promise.nodeify = function (promise, cb) { - promise.then(function (val) { - cb(void 0, val); - }, cb); - }; - Promise.map = function (arr, fn) { - return Promise.all( - arr.map(function (i, el, list) { - return Promise.try(fn, [i, el, list]); - }) - ); - }; - Promise.each = function (arr, fn) { - const queue = arr.slice(0); - let i = 0; - return (function next() { - if (!queue.length) return arr; - return Promise.try(fn, [arr.shift(), i++]).then(next); - })(); - }; - Promise.is = function (obj) { - // $q doesn't create instances of any constructor, promises are just objects with a then function - // https://github.com/angular/angular.js/blob/58f5da86645990ef984353418cd1ed83213b111e/src/ng/q.js#L335 - return obj && typeof obj.then === 'function'; - }; - Promise.halt = _.once(function () { - const promise = new Promise(() => {}); - promise.then = _.constant(promise); - promise.catch = _.constant(promise); - return promise; - }); - Promise.try = function (fn, args, ctx) { - if (typeof fn !== 'function') { - return Promise.reject(new TypeError('fn must be a function')); - } - - let value; - - if (Array.isArray(args)) { - try { - value = fn.apply(ctx, args); - } catch (e) { - return Promise.reject(e); - } - } else { - try { - value = fn.call(ctx, args); - } catch (e) { - return Promise.reject(e); - } - } - - return Promise.resolve(value); - }; - Promise.fromNode = function (takesCbFn) { - return new Promise(function (resolve, reject) { - takesCbFn(function (err, ...results) { - if (err) reject(err); - else if (results.length > 1) resolve(results); - else resolve(results[0]); - }); - }); - }; - Promise.race = function (iterable) { - return new Promise((resolve, reject) => { - for (const i of iterable) { - Promise.resolve(i).then(resolve, reject); - } - }); - }; - - return Promise; -} diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular/subscribe_with_scope.test.ts b/src/plugins/opensearch_dashboards_legacy/public/angular/subscribe_with_scope.test.ts deleted file mode 100644 index 3784988fc818..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular/subscribe_with_scope.test.ts +++ /dev/null @@ -1,208 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 * as Rx from 'rxjs'; -import { subscribeWithScope } from './subscribe_with_scope'; - -// eslint-disable-next-line prefer-const -let $rootScope: Scope; - -class Scope { - public $$phase?: string; - public $root = $rootScope; - public $apply = jest.fn((fn: () => void) => fn()); -} - -$rootScope = new Scope(); - -afterEach(() => { - jest.clearAllMocks(); -}); - -it('subscribes to the passed observable, returns subscription', () => { - const $scope = new Scope(); - - const unsubSpy = jest.fn(); - const subSpy = jest.fn(() => unsubSpy); - const observable = new Rx.Observable(subSpy); - - const subscription = subscribeWithScope($scope as any, observable); - expect(subSpy).toHaveBeenCalledTimes(1); - expect(unsubSpy).not.toHaveBeenCalled(); - - subscription.unsubscribe(); - - expect(subSpy).toHaveBeenCalledTimes(1); - expect(unsubSpy).toHaveBeenCalledTimes(1); -}); - -it('calls observer.next() if already in a digest cycle, wraps in $scope.$apply if not', () => { - const subject = new Rx.Subject(); - const nextSpy = jest.fn(); - const $scope = new Scope(); - - subscribeWithScope($scope as any, subject, { next: nextSpy }); - - subject.next(); - expect($scope.$apply).toHaveBeenCalledTimes(1); - expect(nextSpy).toHaveBeenCalledTimes(1); - - jest.clearAllMocks(); - - $rootScope.$$phase = '$digest'; - subject.next(); - expect($scope.$apply).not.toHaveBeenCalled(); - expect(nextSpy).toHaveBeenCalledTimes(1); -}); - -it('reports fatalError if observer.next() throws', () => { - const fatalError = jest.fn(); - const $scope = new Scope(); - subscribeWithScope( - $scope as any, - Rx.of(undefined), - { - next() { - throw new Error('foo bar'); - }, - }, - fatalError - ); - - expect(fatalError.mock.calls).toMatchInlineSnapshot(` -Array [ - Array [ - [Error: foo bar], - ], -] -`); -}); - -it('reports fatal error if observer.error is not defined and observable errors', () => { - const fatalError = jest.fn(); - const $scope = new Scope(); - const error = new Error('foo'); - error.stack = `${error.message}\n---stack trace ---`; - subscribeWithScope($scope as any, Rx.throwError(error), undefined, fatalError); - - expect(fatalError.mock.calls).toMatchInlineSnapshot(` -Array [ - Array [ - [Error: Uncaught error in subscribeWithScope(): foo ----stack trace ---], - ], -] -`); -}); - -it('reports fatal error if observer.error throws', () => { - const fatalError = jest.fn(); - const $scope = new Scope(); - subscribeWithScope( - $scope as any, - Rx.throwError(new Error('foo')), - { - error: () => { - throw new Error('foo'); - }, - }, - fatalError - ); - - expect(fatalError.mock.calls).toMatchInlineSnapshot(` -Array [ - Array [ - [Error: foo], - ], -] -`); -}); - -it('does not report fatal error if observer.error handles the error', () => { - const fatalError = jest.fn(); - const $scope = new Scope(); - subscribeWithScope( - $scope as any, - Rx.throwError(new Error('foo')), - { - error: () => { - // noop, swallow error - }, - }, - fatalError - ); - - expect(fatalError.mock.calls).toEqual([]); -}); - -it('reports fatal error if observer.complete throws', () => { - const fatalError = jest.fn(); - const $scope = new Scope(); - subscribeWithScope( - $scope as any, - Rx.EMPTY, - { - complete: () => { - throw new Error('foo'); - }, - }, - fatalError - ); - - expect(fatalError.mock.calls).toMatchInlineSnapshot(` -Array [ - Array [ - [Error: foo], - ], -] -`); -}); - -it('preserves the context of the observer functions', () => { - const $scope = new Scope(); - const observer = { - next() { - expect(this).toBe(observer); - }, - complete() { - expect(this).toBe(observer); - }, - }; - - subscribeWithScope($scope as any, Rx.of([1, 2, 3]), observer); - - const observer2 = { - error() { - expect(this).toBe(observer); - }, - }; - - subscribeWithScope($scope as any, Rx.throwError(new Error('foo')), observer2); -}); diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular/subscribe_with_scope.ts b/src/plugins/opensearch_dashboards_legacy/public/angular/subscribe_with_scope.ts deleted file mode 100644 index f8cb102379b6..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular/subscribe_with_scope.ts +++ /dev/null @@ -1,96 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 { IScope } from 'angular'; -import * as Rx from 'rxjs'; -import { AngularHttpError } from '../notify/lib'; - -type FatalErrorFn = (error: AngularHttpError | Error | string, location?: string) => void; - -function callInDigest($scope: IScope, fn: () => void, fatalError?: FatalErrorFn) { - try { - // this is terrible, but necessary to synchronously deliver subscription values - // to angular scopes. This is required by some APIs, like the `config` service, - // and beneficial for root level directives where additional digest cycles make - // opensearch dashboards sluggish to load. - // - // If you copy this code elsewhere you better have a good reason :) - if ($scope.$root.$$phase) { - fn(); - } else { - $scope.$apply(() => fn()); - } - } catch (error) { - if (fatalError) { - fatalError(error); - } - } -} - -/** - * Subscribe to an observable at a $scope, ensuring that the digest cycle - * is run for subscriber hooks and routing errors to fatalError if not handled. - */ -export function subscribeWithScope( - $scope: IScope, - observable: Rx.Observable, - observer?: Rx.PartialObserver, - fatalError?: FatalErrorFn -) { - return observable.subscribe({ - next(value) { - if (observer && observer.next) { - callInDigest($scope, () => observer.next!(value), fatalError); - } - }, - error(error) { - callInDigest( - $scope, - () => { - if (observer && observer.error) { - observer.error(error); - } else { - throw new Error( - `Uncaught error in subscribeWithScope(): ${ - error ? error.stack || error.message : error - }` - ); - } - }, - fatalError - ); - }, - complete() { - if (observer && observer.complete) { - callInDigest($scope, () => observer.complete!(), fatalError); - } - }, - }); -} diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular/watch_multi.js b/src/plugins/opensearch_dashboards_legacy/public/angular/watch_multi.js deleted file mode 100644 index 8dfcb0f59420..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular/watch_multi.js +++ /dev/null @@ -1,159 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * 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 _ from 'lodash'; - -export function watchMultiDecorator($provide) { - $provide.decorator('$rootScope', function ($delegate) { - /** - * Watch multiple expressions with a single callback. Along - * with making code simpler it also merges all of the watcher - * handlers within a single tick. - * - * # expression format - * expressions can be specified in one of the following ways: - * 1. string that evaluates to a value on scope. Creates a regular $watch - * expression. - * 'someScopeValue.prop' === $scope.$watch('someScopeValue.prop', fn); - * - * 2. #1 prefixed with '[]', which uses $watchCollection rather than $watch. - * '[]expr' === $scope.$watchCollection('expr', fn); - * - * 3. #1 prefixed with '=', which uses $watch with objectEquality turned on - * '=expr' === $scope.$watch('expr', fn, true); - * - * 4. a function that will be called, like a normal function water - * - * 5. an object with any of the properties: - * `get`: the getter called on each iteration - * `deep`: a flag to turn on objectEquality in $watch - * `fn`: the watch registration function ($scope.$watch or $scope.$watchCollection) - * - * @param {array[string|function|obj]} expressions - the list of expressions to $watch - * @param {Function} fn - the callback function - * @return {Function} - an unwatch function, just like the return value of $watch - */ - $delegate.constructor.prototype.$watchMulti = function (expressions, fn) { - if (!Array.isArray(expressions)) { - throw new TypeError('expected an array of expressions to watch'); - } - - if (!_.isFunction(fn)) { - throw new TypeError('expected a function that is triggered on each watch'); - } - const $scope = this; - const vals = new Array(expressions.length); - const prev = new Array(expressions.length); - let fire = false; - let init = 0; - const neededInits = expressions.length; - - // first, register all of the multi-watchers - const unwatchers = expressions.map(function (expr, i) { - expr = normalizeExpression($scope, expr); - if (!expr) return; - - return expr.fn.call( - $scope, - expr.get, - function (newVal, oldVal) { - if (newVal === oldVal) { - init += 1; - } - - vals[i] = newVal; - prev[i] = oldVal; - fire = true; - }, - expr.deep - ); - }); - - // then, the watcher that checks to see if any of - // the other watchers triggered this cycle - let flip = false; - unwatchers.push( - $scope.$watch( - function () { - if (init < neededInits) return init; - - if (fire) { - fire = false; - flip = !flip; - } - return flip; - }, - function () { - if (init < neededInits) return false; - - fn(vals.slice(0), prev.slice(0)); - vals.forEach(function (v, i) { - prev[i] = v; - }); - } - ) - ); - - return function () { - unwatchers.forEach((listener) => listener()); - }; - }; - - function normalizeExpression($scope, expr) { - if (!expr) return; - const norm = { - fn: $scope.$watch, - deep: false, - }; - - if (_.isFunction(expr)) return _.assign(norm, { get: expr }); - if (_.isObject(expr)) return _.assign(norm, expr); - if (!_.isString(expr)) return; - - if (expr.substr(0, 2) === '[]') { - return _.assign(norm, { - fn: $scope.$watchCollection, - get: expr.substr(2), - }); - } - - if (expr.charAt(0) === '=') { - return _.assign(norm, { - deep: true, - get: expr.substr(1), - }); - } - - return _.assign(norm, { get: expr }); - } - - return $delegate; - }); -} diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/bind_html/bind_html.js b/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/bind_html/bind_html.js deleted file mode 100755 index 5e6f2edea608..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/bind_html/bind_html.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* eslint-disable */ - -import angular from 'angular'; - -export function initBindHtml() { - angular - .module('ui.bootstrap.bindHtml', []) - - .directive('bindHtmlUnsafe', function() { - return function(scope, element, attr) { - element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); - scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { - element.html(value || ''); - }); - }; - }); -} diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/index.ts b/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/index.ts deleted file mode 100644 index 63b0431ebb29..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* eslint-disable */ - -import { once } from 'lodash'; -import angular from 'angular'; - -// @ts-ignore -import { initBindHtml } from './bind_html/bind_html'; -// @ts-ignore -import { initBootstrapTooltip } from './tooltip/tooltip'; - -import tooltipPopup from './tooltip/tooltip_popup.html'; - -import tooltipUnsafePopup from './tooltip/tooltip_html_unsafe_popup.html'; - -export const initAngularBootstrap = once(() => { - /* - * angular-ui-bootstrap - * http://angular-ui.github.io/bootstrap/ - - * Version: 0.12.1 - 2015-02-20 - * License: MIT - */ - angular.module('ui.bootstrap', [ - 'ui.bootstrap.tpls', - 'ui.bootstrap.bindHtml', - 'ui.bootstrap.tooltip', - ]); - - angular.module('ui.bootstrap.tpls', [ - 'template/tooltip/tooltip-html-unsafe-popup.html', - 'template/tooltip/tooltip-popup.html', - ]); - - initBindHtml(); - initBootstrapTooltip(); - - angular.module('template/tooltip/tooltip-html-unsafe-popup.html', []).run([ - '$templateCache', - function($templateCache: any) { - $templateCache.put('template/tooltip/tooltip-html-unsafe-popup.html', tooltipUnsafePopup); - }, - ]); - - angular.module('template/tooltip/tooltip-popup.html', []).run([ - '$templateCache', - function($templateCache: any) { - $templateCache.put('template/tooltip/tooltip-popup.html', tooltipPopup); - }, - ]); -}); diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/position.js b/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/position.js deleted file mode 100755 index 2f322e2b42e2..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/position.js +++ /dev/null @@ -1,178 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* eslint-disable */ - -import angular from 'angular'; - -export function initBootstrapPosition() { - angular - .module('ui.bootstrap.position', []) - - /** - * A set of utility methods that can be use to retrieve position of DOM elements. - * It is meant to be used where we need to absolute-position DOM elements in - * relation to other, existing elements (this is the case for tooltips, popovers, - * typeahead suggestions etc.). - */ - .factory('$position', [ - '$document', - '$window', - function($document, $window) { - function getStyle(el, cssprop) { - if (el.currentStyle) { - //IE - return el.currentStyle[cssprop]; - } else if ($window.getComputedStyle) { - return $window.getComputedStyle(el)[cssprop]; - } - // finally try and get inline style - return el.style[cssprop]; - } - - /** - * Checks if a given element is statically positioned - * @param element - raw DOM element - */ - function isStaticPositioned(element) { - return (getStyle(element, 'position') || 'static') === 'static'; - } - - /** - * returns the closest, non-statically positioned parentOffset of a given element - * @param element - */ - const parentOffsetEl = function(element) { - const docDomEl = $document[0]; - let offsetParent = element.offsetParent || docDomEl; - while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent)) { - offsetParent = offsetParent.offsetParent; - } - return offsetParent || docDomEl; - }; - - return { - /** - * Provides read-only equivalent of jQuery's position function: - * http://api.jquery.com/position/ - */ - position: function(element) { - const elBCR = this.offset(element); - let offsetParentBCR = { top: 0, left: 0 }; - const offsetParentEl = parentOffsetEl(element[0]); - if (offsetParentEl != $document[0]) { - offsetParentBCR = this.offset(angular.element(offsetParentEl)); - offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop; - offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft; - } - - const boundingClientRect = element[0].getBoundingClientRect(); - return { - width: boundingClientRect.width || element.prop('offsetWidth'), - height: boundingClientRect.height || element.prop('offsetHeight'), - top: elBCR.top - offsetParentBCR.top, - left: elBCR.left - offsetParentBCR.left, - }; - }, - - /** - * Provides read-only equivalent of jQuery's offset function: - * http://api.jquery.com/offset/ - */ - offset: function(element) { - const boundingClientRect = element[0].getBoundingClientRect(); - return { - width: boundingClientRect.width || element.prop('offsetWidth'), - height: boundingClientRect.height || element.prop('offsetHeight'), - top: - boundingClientRect.top + - ($window.pageYOffset || $document[0].documentElement.scrollTop), - left: - boundingClientRect.left + - ($window.pageXOffset || $document[0].documentElement.scrollLeft), - }; - }, - - /** - * Provides coordinates for the targetEl in relation to hostEl - */ - positionElements: function(hostEl, targetEl, positionStr, appendToBody) { - const positionStrParts = positionStr.split('-'); - const pos0 = positionStrParts[0]; - const pos1 = positionStrParts[1] || 'center'; - - let hostElPos; - let targetElWidth; - let targetElHeight; - let targetElPos; - - hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); - - targetElWidth = targetEl.prop('offsetWidth'); - targetElHeight = targetEl.prop('offsetHeight'); - - const shiftWidth = { - center: function() { - return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; - }, - left: function() { - return hostElPos.left; - }, - right: function() { - return hostElPos.left + hostElPos.width; - }, - }; - - const shiftHeight = { - center: function() { - return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; - }, - top: function() { - return hostElPos.top; - }, - bottom: function() { - return hostElPos.top + hostElPos.height; - }, - }; - - switch (pos0) { - case 'right': - targetElPos = { - top: shiftHeight[pos1](), - left: shiftWidth[pos0](), - }; - break; - case 'left': - targetElPos = { - top: shiftHeight[pos1](), - left: hostElPos.left - targetElWidth, - }; - break; - case 'bottom': - targetElPos = { - top: shiftHeight[pos0](), - left: shiftWidth[pos1](), - }; - break; - default: - targetElPos = { - top: hostElPos.top - targetElHeight, - left: shiftWidth[pos1](), - }; - break; - } - - return targetElPos; - }, - }; - }, - ]); -} diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip.js b/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip.js deleted file mode 100755 index 086fa6a7d6df..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip.js +++ /dev/null @@ -1,434 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* eslint-disable */ - -import angular from 'angular'; - -import { initBootstrapPosition } from './position'; - -export function initBootstrapTooltip() { - initBootstrapPosition(); - /** - * The following features are still outstanding: animation as a - * function, placement as a function, inside, support for more triggers than - * just mouse enter/leave, html tooltips, and selector delegation. - */ - angular - .module('ui.bootstrap.tooltip', ['ui.bootstrap.position']) - - /** - * The $tooltip service creates tooltip- and popover-like directives as well as - * houses global options for them. - */ - .provider('$tooltip', function() { - // The default options tooltip and popover. - const defaultOptions = { - placement: 'top', - animation: true, - popupDelay: 0, - }; - - // Default hide triggers for each show trigger - const triggerMap = { - mouseenter: 'mouseleave', - click: 'click', - focus: 'blur', - }; - - // The options specified to the provider globally. - const globalOptions = {}; - - /** - * `options({})` allows global configuration of all tooltips in the - * application. - * - * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) { - * // place tooltips left instead of top by default - * $tooltipProvider.options( { placement: 'left' } ); - * }); - */ - this.options = function(value) { - angular.extend(globalOptions, value); - }; - - /** - * This allows you to extend the set of trigger mappings available. E.g.: - * - * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' ); - */ - this.setTriggers = function setTriggers(triggers) { - angular.extend(triggerMap, triggers); - }; - - /** - * This is a helper function for translating camel-case to snake-case. - */ - function snake_case(name) { - const regexp = /[A-Z]/g; - const separator = '-'; - return name.replace(regexp, function(letter, pos) { - return (pos ? separator : '') + letter.toLowerCase(); - }); - } - - /** - * Returns the actual instance of the $tooltip service. - * TODO support multiple triggers - */ - this.$get = [ - '$window', - '$compile', - '$timeout', - '$document', - '$position', - '$interpolate', - function($window, $compile, $timeout, $document, $position, $interpolate) { - return function $tooltip(type, prefix, defaultTriggerShow) { - const options = angular.extend({}, defaultOptions, globalOptions); - - /** - * Returns an object of show and hide triggers. - * - * If a trigger is supplied, - * it is used to show the tooltip; otherwise, it will use the `trigger` - * option passed to the `$tooltipProvider.options` method; else it will - * default to the trigger supplied to this directive factory. - * - * The hide trigger is based on the show trigger. If the `trigger` option - * was passed to the `$tooltipProvider.options` method, it will use the - * mapped trigger from `triggerMap` or the passed trigger if the map is - * undefined; otherwise, it uses the `triggerMap` value of the show - * trigger; else it will just use the show trigger. - */ - function getTriggers(trigger) { - const show = trigger || options.trigger || defaultTriggerShow; - const hide = triggerMap[show] || show; - return { - show: show, - hide: hide, - }; - } - - const directiveName = snake_case(type); - - const startSym = $interpolate.startSymbol(); - const endSym = $interpolate.endSymbol(); - const template = - '
' + - '
'; - - return { - restrict: 'EA', - compile: function(tElem, tAttrs) { - const tooltipLinker = $compile(template); - - return function link(scope, element, attrs) { - let tooltip; - let tooltipLinkedScope; - let transitionTimeout; - let popupTimeout; - let appendToBody = angular.isDefined(options.appendToBody) - ? options.appendToBody - : false; - let triggers = getTriggers(undefined); - const hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']); - let ttScope = scope.$new(true); - - const positionTooltip = function() { - const ttPosition = $position.positionElements( - element, - tooltip, - ttScope.placement, - appendToBody - ); - ttPosition.top += 'px'; - ttPosition.left += 'px'; - - // Now set the calculated positioning. - tooltip.css(ttPosition); - }; - - // By default, the tooltip is not open. - // TODO add ability to start tooltip opened - ttScope.isOpen = false; - - function toggleTooltipBind() { - if (!ttScope.isOpen) { - showTooltipBind(); - } else { - hideTooltipBind(); - } - } - - // Show the tooltip with delay if specified, otherwise show it immediately - function showTooltipBind() { - if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) { - return; - } - - prepareTooltip(); - - if (ttScope.popupDelay) { - // Do nothing if the tooltip was already scheduled to pop-up. - // This happens if show is triggered multiple times before any hide is triggered. - if (!popupTimeout) { - popupTimeout = $timeout(show, ttScope.popupDelay, false); - popupTimeout - .then(reposition => reposition()) - .catch(error => { - // if the timeout is canceled then the string `canceled` is thrown. To prevent - // this from triggering an 'unhandled promise rejection' in angular 1.5+ the - // $timeout service explicitly tells $q that the promise it generated is "handled" - // but that does not include down chain promises like the one created by calling - // `popupTimeout.then()`. Because of this we need to ignore the "canceled" string - // and only propagate real errors - if (error !== 'canceled') { - throw error; - } - }); - } - } else { - show()(); - } - } - - function hideTooltipBind() { - scope.$evalAsync(function() { - hide(); - }); - } - - // Show the tooltip popup element. - function show() { - popupTimeout = null; - - // If there is a pending remove transition, we must cancel it, lest the - // tooltip be mysteriously removed. - if (transitionTimeout) { - $timeout.cancel(transitionTimeout); - transitionTimeout = null; - } - - // Don't show empty tooltips. - if (!ttScope.content) { - return angular.noop; - } - - createTooltip(); - - // Set the initial positioning. - tooltip.css({ top: 0, left: 0, display: 'block' }); - ttScope.$digest(); - - positionTooltip(); - - // And show the tooltip. - ttScope.isOpen = true; - ttScope.$digest(); // digest required as $apply is not called - - // Return positioning function as promise callback for correct - // positioning after draw. - return positionTooltip; - } - - // Hide the tooltip popup element. - function hide() { - // First things first: we don't show it anymore. - ttScope.isOpen = false; - - //if tooltip is going to be shown after delay, we must cancel this - $timeout.cancel(popupTimeout); - popupTimeout = null; - - // And now we remove it from the DOM. However, if we have animation, we - // need to wait for it to expire beforehand. - // FIXME: this is a placeholder for a port of the transitions library. - if (ttScope.animation) { - if (!transitionTimeout) { - transitionTimeout = $timeout(removeTooltip, 500); - } - } else { - removeTooltip(); - } - } - - function createTooltip() { - // There can only be one tooltip element per directive shown at once. - if (tooltip) { - removeTooltip(); - } - tooltipLinkedScope = ttScope.$new(); - tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) { - if (appendToBody) { - $document.find('body').append(tooltip); - } else { - element.after(tooltip); - } - }); - } - - function removeTooltip() { - transitionTimeout = null; - if (tooltip) { - tooltip.remove(); - tooltip = null; - } - if (tooltipLinkedScope) { - tooltipLinkedScope.$destroy(); - tooltipLinkedScope = null; - } - } - - function prepareTooltip() { - prepPlacement(); - prepPopupDelay(); - } - - /** - * Observe the relevant attributes. - */ - attrs.$observe(type, function(val) { - ttScope.content = val; - - if (!val && ttScope.isOpen) { - hide(); - } - }); - - attrs.$observe(prefix + 'Title', function(val) { - ttScope.title = val; - }); - - function prepPlacement() { - const val = attrs[prefix + 'Placement']; - ttScope.placement = angular.isDefined(val) ? val : options.placement; - } - - function prepPopupDelay() { - const val = attrs[prefix + 'PopupDelay']; - const delay = parseInt(val, 10); - ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay; - } - - const unregisterTriggers = function() { - element.unbind(triggers.show, showTooltipBind); - element.unbind(triggers.hide, hideTooltipBind); - }; - - function prepTriggers() { - const val = attrs[prefix + 'Trigger']; - unregisterTriggers(); - - triggers = getTriggers(val); - - if (triggers.show === triggers.hide) { - element.bind(triggers.show, toggleTooltipBind); - } else { - element.bind(triggers.show, showTooltipBind); - element.bind(triggers.hide, hideTooltipBind); - } - } - - prepTriggers(); - - const animation = scope.$eval(attrs[prefix + 'Animation']); - ttScope.animation = angular.isDefined(animation) - ? !!animation - : options.animation; - - const appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']); - appendToBody = angular.isDefined(appendToBodyVal) - ? appendToBodyVal - : appendToBody; - - // if a tooltip is attached to we need to remove it on - // location change as its parent scope will probably not be destroyed - // by the change. - if (appendToBody) { - scope.$on( - '$locationChangeSuccess', - function closeTooltipOnLocationChangeSuccess() { - if (ttScope.isOpen) { - hide(); - } - } - ); - } - - // Make sure tooltip is destroyed and removed. - scope.$on('$destroy', function onDestroyTooltip() { - $timeout.cancel(transitionTimeout); - $timeout.cancel(popupTimeout); - unregisterTriggers(); - removeTooltip(); - ttScope = null; - }); - }; - }, - }; - }; - }, - ]; - }) - - .directive('tooltip', [ - '$tooltip', - function($tooltip) { - return $tooltip('tooltip', 'tooltip', 'mouseenter'); - }, - ]) - - .directive('tooltipPopup', function() { - return { - restrict: 'EA', - replace: true, - scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, - templateUrl: 'template/tooltip/tooltip-popup.html', - }; - }) - - .directive('tooltipHtmlUnsafe', [ - '$tooltip', - function($tooltip) { - return $tooltip('tooltipHtmlUnsafe', 'tooltip', 'mouseenter'); - }, - ]) - - .directive('tooltipHtmlUnsafePopup', function() { - return { - restrict: 'EA', - replace: true, - scope: { content: '@', placement: '@', animation: '&', isOpen: '&' }, - templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html', - }; - }); -} diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip_html_unsafe_popup.html b/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip_html_unsafe_popup.html deleted file mode 100644 index b48bf7049890..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip_html_unsafe_popup.html +++ /dev/null @@ -1,4 +0,0 @@ -
-
-
-
\ No newline at end of file diff --git a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip_popup.html b/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip_popup.html deleted file mode 100644 index eed4ca7d9301..000000000000 --- a/src/plugins/opensearch_dashboards_legacy/public/angular_bootstrap/tooltip/tooltip_popup.html +++ /dev/null @@ -1,4 +0,0 @@ -
-
-
-
\ No newline at end of file diff --git a/src/plugins/opensearch_dashboards_legacy/public/index.ts b/src/plugins/opensearch_dashboards_legacy/public/index.ts index 67cd6def9f0f..ec74afc903f6 100644 --- a/src/plugins/opensearch_dashboards_legacy/public/index.ts +++ b/src/plugins/opensearch_dashboards_legacy/public/index.ts @@ -36,8 +36,6 @@ export const plugin = (initializerContext: PluginInitializerContext) => export * from './plugin'; -export { initAngularBootstrap } from './angular_bootstrap'; export { PaginateDirectiveProvider, PaginateControlsDirectiveProvider } from './paginate/paginate'; -export * from './angular'; export * from './notify'; export * from './utils'; diff --git a/src/plugins/tile_map/public/plugin.ts b/src/plugins/tile_map/public/plugin.ts index 4b6b76ae193d..37d6d3e14c00 100644 --- a/src/plugins/tile_map/public/plugin.ts +++ b/src/plugins/tile_map/public/plugin.ts @@ -38,7 +38,7 @@ import { import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; // TODO: Determine why visualizations don't populate without this -import 'angular-sanitize'; +// import 'angular-sanitize'; // @ts-ignore import { createTileMapFn } from './tile_map_fn'; diff --git a/yarn.lock b/yarn.lock index 544864b2e711..6df97ecb5926 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2838,18 +2838,6 @@ resolved "https://registry.yarnpkg.com/@tsd/typescript/-/typescript-4.7.4.tgz#f1e4e6c3099a174a0cb7aa51cf53f34f6494e528" integrity sha512-jbtC+RgKZ9Kk65zuRZbKLTACf+tvFW4Rfq0JEMXrlmV3P3yme+Hm+pnb5fJRyt61SjIitcrC810wj7+1tgsEmg== -"@types/angular-mocks@^1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@types/angular-mocks/-/angular-mocks-1.7.1.tgz#0f18066f8e6f327493aad0c280a43801ffa09464" - integrity sha512-44kaQL8sMGUIDV76zbJ3MX6aqPng7Wmfz91uds+WcNQFHTdSu6KDZNIypIZVAdrWnJfqrfL5VysaCejTW3JVIw== - dependencies: - "@types/angular" "*" - -"@types/angular@*", "@types/angular@^1.8.4": - version "1.8.4" - resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.8.4.tgz#a2cc163e508389c51d4c4119ebff6b9395cec472" - integrity sha512-wPS/ncJWhyxJsndsW1B6Ta8D4mi97x1yItSu+rkLDytU3oRIh2CFAjMuJceYwFAh9+DIohndWM0QBA9OU2Hv0g== - "@types/archiver@^5.3.1": version "5.3.1" resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-5.3.1.tgz#02991e940a03dd1a32678fead4b4ca03d0e387ca" @@ -4392,43 +4380,6 @@ ajv@^8.0.1, ajv@^8.11.0, ajv@^8.6.2: require-from-string "^2.0.2" uri-js "^4.2.2" -angular-aria@^1.8.0: - version "1.8.2" - resolved "https://registry.yarnpkg.com/angular-aria/-/angular-aria-1.8.2.tgz#3e5d546e549d8bddcf0b8031c677d3129d82a76d" - integrity sha512-xWT1Lm+Xug2GM6nGNMioBP4hXt3sj2eGaExa4cVCZUYSVWezgyuD1RiLgzJzwTkBGYplHQUzQaz3yDY8jVI6yQ== - -angular-elastic@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/angular-elastic/-/angular-elastic-2.5.1.tgz#e938ab1bd8c76415b8ca6514b15fe3593a5df535" - integrity sha1-6TirG9jHZBW4ymUUsV/jWTpd9TU= - dependencies: - angular ">=1.0.6" - -angular-mocks@^1.8.2: - version "1.8.2" - resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.8.2.tgz#dc022420b86978cf317a8447c116c0be73a853bf" - integrity sha512-I5L3P0l21HPdVsP4A4qWmENt4ePjjbkDFdAzOaM7QiibFySbt14DptPbt2IjeG4vFBr4vSLbhIz8Fk03DISl8Q== - -angular-recursion@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/angular-recursion/-/angular-recursion-1.0.5.tgz#cd405428a0bf55faf52eaa7988c1fe69cd930543" - integrity sha1-zUBUKKC/Vfr1Lqp5iMH+ac2TBUM= - -angular-route@^1.8.0: - version "1.8.2" - resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.8.2.tgz#d482bf05a8c9e448300acd8f9989c635d31b5077" - integrity sha512-49LJYxuaQ/ZDiu9dD2xo1LkazqObkGjw0a7dUF7UKCT8EELgBsMd6QrI6aEVGtI62ppkiFkxqmiV8fcwYdXpug== - -angular-sanitize@^1.8.0: - version "1.8.2" - resolved "https://registry.yarnpkg.com/angular-sanitize/-/angular-sanitize-1.8.2.tgz#ae78040f00c5e2ce1c63780bcc47fa14a1698296" - integrity sha512-OB6Goa+QN3byf5asQ7XRl7DKZejm/F/ZOqa9z1skqYVOWA2hoBxoCmt9E7+i7T/TbxZP5zYzKxNZVVJNu860Hg== - -angular@>=1.0.6, angular@^1.8.2: - version "1.8.2" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.2.tgz#5983bbb5a9fa63e213cb7749199e0d352de3a2f1" - integrity sha512-IauMOej2xEe7/7Ennahkbb5qd/HFADiNuLSESz9Q27inmi32zB0lnAsFeLEWcox3Gd1F6YhNd1CP7/9IukJ0Gw== - ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"