From ca3f4de7d7a4003d5e6796f11894bfa164a216c4 Mon Sep 17 00:00:00 2001 From: igoristic Date: Mon, 25 Jan 2021 21:01:50 -0500 Subject: [PATCH 01/21] [Monitoring] No longer overwriting time to the 1h default (#88102) * No longer overwriting time to the 1h default * Added auto refresh --- x-pack/plugins/monitoring/public/plugin.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/x-pack/plugins/monitoring/public/plugin.ts b/x-pack/plugins/monitoring/public/plugin.ts index a0de3a7663a12..52f8d07f4fdb6 100644 --- a/x-pack/plugins/monitoring/public/plugin.ts +++ b/x-pack/plugins/monitoring/public/plugin.ts @@ -18,7 +18,6 @@ import { FeatureCatalogueCategory, HomePublicPluginSetup, } from '../../../../src/plugins/home/public'; -import { UI_SETTINGS } from '../../../../src/plugins/data/public'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { MonitoringStartPluginDependencies, MonitoringConfig } from './types'; import { TriggersAndActionsUIPublicPluginSetup } from '../../triggers_actions_ui/public'; @@ -98,7 +97,6 @@ export class MonitoringPlugin }; this.setInitialTimefilter(deps); - const monitoringApp = new AngularApp(deps); const removeHistoryListener = params.history.listen((location) => { if (location.pathname === '' && location.hash === '') { @@ -121,18 +119,10 @@ export class MonitoringPlugin public stop() {} - private setInitialTimefilter({ core: coreContext, data }: MonitoringStartPluginDependencies) { + private setInitialTimefilter({ data }: MonitoringStartPluginDependencies) { const { timefilter } = data.query.timefilter; - const { uiSettings } = coreContext; const refreshInterval = { value: 10000, pause: false }; - const time = { from: 'now-1h', to: 'now' }; timefilter.setRefreshInterval(refreshInterval); - timefilter.setTime(time); - uiSettings.overrideLocalDefault( - UI_SETTINGS.TIMEPICKER_REFRESH_INTERVAL_DEFAULTS, - JSON.stringify(refreshInterval) - ); - uiSettings.overrideLocalDefault(UI_SETTINGS.TIMEPICKER_TIME_DEFAULTS, JSON.stringify(time)); } private getExternalConfig() { From 1750fc269c0b7784acd0c241b86618132e9a75e1 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 25 Jan 2021 21:10:05 -0500 Subject: [PATCH 02/21] [Monitoring] Fix newly added cloud link (#89067) * Fix cloud link * Update link * Fix tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/no_data/blurbs/cloud_deployment.js | 4 +++- .../exporters/__snapshots__/exporters.test.js.snap | 2 +- .../no_data/explanations/exporters/exporters.test.js | 10 ++++++++++ .../reasons/__snapshots__/reason_found.test.js.snap | 2 +- .../components/no_data/reasons/reason_found.test.js | 10 ++++++++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/monitoring/public/components/no_data/blurbs/cloud_deployment.js b/x-pack/plugins/monitoring/public/components/no_data/blurbs/cloud_deployment.js index c01243fdeec47..e1262771f94a3 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/blurbs/cloud_deployment.js +++ b/x-pack/plugins/monitoring/public/components/no_data/blurbs/cloud_deployment.js @@ -7,8 +7,10 @@ import React from 'react'; import { EuiText, EuiTextColor, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { Legacy } from '../../../legacy_shims'; export const CloudDeployment = () => { + const { ELASTIC_WEBSITE_URL } = Legacy.shims.docLinks; return ( @@ -32,7 +34,7 @@ export const CloudDeployment = () => { defaultMessage="section for a deployment to configure monitoring. For more information visit " /> the documentation page. diff --git a/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/__snapshots__/exporters.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/__snapshots__/exporters.test.js.snap index 99f5a979c812b..6bfc17121d511 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/__snapshots__/exporters.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/__snapshots__/exporters.test.js.snap @@ -135,7 +135,7 @@ Array [ section for a deployment to configure monitoring. For more information visit diff --git a/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/exporters.test.js b/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/exporters.test.js index 2bc581ffb1abb..280572b000011 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/exporters.test.js +++ b/x-pack/plugins/monitoring/public/components/no_data/explanations/exporters/exporters.test.js @@ -8,6 +8,16 @@ import React from 'react'; import { renderWithIntl } from '@kbn/test/jest'; import { ExplainExporters, ExplainExportersCloud } from './exporters'; +jest.mock('../../../../legacy_shims', () => ({ + Legacy: { + shims: { + docLinks: { + ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', + }, + }, + }, +})); + describe('ExplainExporters', () => { test('should explain about xpack.monitoring.exporters setting', () => { const reason = { diff --git a/x-pack/plugins/monitoring/public/components/no_data/reasons/__snapshots__/reason_found.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/reasons/__snapshots__/reason_found.test.js.snap index e3d25f97c9f78..649d5f7f757ab 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/reasons/__snapshots__/reason_found.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/no_data/reasons/__snapshots__/reason_found.test.js.snap @@ -210,7 +210,7 @@ Array [ section for a deployment to configure monitoring. For more information visit diff --git a/x-pack/plugins/monitoring/public/components/no_data/reasons/reason_found.test.js b/x-pack/plugins/monitoring/public/components/no_data/reasons/reason_found.test.js index b4abda87ea1e0..b18351f22851e 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/reasons/reason_found.test.js +++ b/x-pack/plugins/monitoring/public/components/no_data/reasons/reason_found.test.js @@ -8,6 +8,16 @@ import React from 'react'; import { renderWithIntl } from '@kbn/test/jest'; import { ReasonFound } from '.'; +jest.mock('../../../legacy_shims', () => ({ + Legacy: { + shims: { + docLinks: { + ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', + }, + }, + }, +})); + const enabler = {}; describe('ReasonFound', () => { From da72cd47b2d36ef39f22ae34594cbbe7533b7859 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 25 Jan 2021 21:11:32 -0500 Subject: [PATCH 03/21] Add toast for newly created alerts (#89202) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/alerts/lib/alerts_toast.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/x-pack/plugins/monitoring/public/alerts/lib/alerts_toast.tsx b/x-pack/plugins/monitoring/public/alerts/lib/alerts_toast.tsx index f478545046894..302a7f2fe469f 100644 --- a/x-pack/plugins/monitoring/public/alerts/lib/alerts_toast.tsx +++ b/x-pack/plugins/monitoring/public/alerts/lib/alerts_toast.tsx @@ -81,6 +81,24 @@ const showUnableToDisableWatcherClusterAlertsError = () => { }); }; +const showDisabledWatcherClusterAlertsError = () => { + Legacy.shims.toastNotifications.addWarning({ + title: toMountPoint( + + ), + text: toMountPoint( +

+ {i18n.translate('xpack.monitoring.healthCheck.disabledWatches.text', { + defaultMessage: `Review the alert definition using Setup mode and configure additional action connectors to get notified via your favorite method.`, + })} +

+ ), + }); +}; + export const showAlertsToast = (response: EnableAlertResponse) => { const { isSufficientlySecure, @@ -92,5 +110,7 @@ export const showAlertsToast = (response: EnableAlertResponse) => { showTlsAndEncryptionError(); } else if (disabledWatcherClusterAlerts === false) { showUnableToDisableWatcherClusterAlertsError(); + } else if (disabledWatcherClusterAlerts === true) { + showDisabledWatcherClusterAlertsError(); } }; From bc840b1c46a201bd158afeb8de2774ead5629947 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 26 Jan 2021 02:51:03 +0000 Subject: [PATCH 04/21] skip flaky suite (#89191) --- src/core/server/ui_settings/integration_tests/routes.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/server/ui_settings/integration_tests/routes.test.ts b/src/core/server/ui_settings/integration_tests/routes.test.ts index 89f5b6732a8fb..2f0a5ebc139e6 100644 --- a/src/core/server/ui_settings/integration_tests/routes.test.ts +++ b/src/core/server/ui_settings/integration_tests/routes.test.ts @@ -9,7 +9,8 @@ import { schema } from '@kbn/config-schema'; import * as kbnTestServer from '../../../test_helpers/kbn_server'; -describe('ui settings service', () => { +// FLAKY: https://github.com/elastic/kibana/issues/89191 +describe.skip('ui settings service', () => { describe('routes', () => { let root: ReturnType; beforeAll(async () => { From f5e869189b0bbf242637a2fb8f06c1e5e74633b7 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Tue, 26 Jan 2021 05:54:10 +0100 Subject: [PATCH 05/21] Improve documentation for index pattern custom label (#89137) Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> --- docs/management/index-patterns.asciidoc | 5 ++++- .../images/edit-field-format.png | Bin 45776 -> 99547 bytes docs/management/managing-fields.asciidoc | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) mode change 100755 => 100644 docs/management/index-patterns/images/edit-field-format.png diff --git a/docs/management/index-patterns.asciidoc b/docs/management/index-patterns.asciidoc index d83f2571ad26f..28dbacc628ce9 100644 --- a/docs/management/index-patterns.asciidoc +++ b/docs/management/index-patterns.asciidoc @@ -158,10 +158,13 @@ date values in {es}, you can use a {kib} field formatter to change the display t <>, and <>. +To customize the displayed field name provided by {es}, you can +use *Custom Label* . + A popularity counter keeps track of the fields you use most often. The top five most popular fields and their values are displayed in <>. -To edit the field format and popularity counter, click the edit icon +To edit the field display, click the edit icon (image:management/index-patterns/images/edit_icon.png[]) in the index pattern detail view. [role="screenshot"] diff --git a/docs/management/index-patterns/images/edit-field-format.png b/docs/management/index-patterns/images/edit-field-format.png old mode 100755 new mode 100644 index 15ab0c5bf876398f478f04594a31d3791cbca252..1ad29d82d2590dd124cdbcafbe0bc990d030100a GIT binary patch literal 99547 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 diff --git a/docs/management/managing-fields.asciidoc b/docs/management/managing-fields.asciidoc index 1b9d22699d359..97cd184a4db88 100644 --- a/docs/management/managing-fields.asciidoc +++ b/docs/management/managing-fields.asciidoc @@ -18,6 +18,7 @@ To format a field: . Open the main menu, and click *Stack Management > Index Patterns*. . Click the index pattern that contains the field you want to format. . Find the field you want to format and click the edit icon (image:management/index-patterns/images/edit_icon.png[]). +. Enter a custom label for the field, if needed. . Select a format and fill in the details. + [role="screenshot"] From ad953ee04eea83f27b89a6ef097d9253802a79f8 Mon Sep 17 00:00:00 2001 From: Daniil Date: Tue, 26 Jan 2021 10:57:09 +0300 Subject: [PATCH 06/21] [Visualizations] Changes in custom visualizations support (#88317) * Convert to typescript * Move related files directly into plugin * Implement toExpressionAst * Remove build_pipeline dedicated fn * Async import converter * Create a custom renderer * Move function directly into plugin * Update tests * Move files directly into related plugins * Remove ExprVis instance usage in maps visualizations * Use uiState updates * Fix minor issues * Update expression builder * Update styles * Create wrapper component * Update rendering * Create region map expression renderer * Fix tests and types * Fix initial render * Remove resize subscription * Fix custom visualization expression * Update region map expression in tests * Update files structure * Remove ReactVisController * Remove base visualization renderer * Remove extra vis properties * Use requiresSearch flag for agg based vis * Update types * Remove visualization expression function * Create toExpressionAst function * Update custom visualization example * Update interpreter functional tests * Enhance VisTypeDefinition interface * Enhance visualization types * Update license Co-authored-by: Alexey Antonov Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/editor/controls_tab.test.tsx | 2 - .../public/components/editor/controls_tab.tsx | 4 +- .../public/components/editor/index.tsx | 6 +- .../public/components/editor/options_tab.tsx | 4 +- .../public/input_control_vis_type.ts | 5 +- .../region_map/public/components/index.tsx | 4 +- .../public/components/region_map_options.tsx | 4 +- .../region_map/public/region_map_type.ts | 5 +- src/plugins/region_map/public/to_ast.ts | 4 +- .../public/components/tile_map_options.tsx | 4 +- src/plugins/tile_map/public/tile_map_type.ts | 5 +- src/plugins/tile_map/public/to_ast.ts | 4 +- .../components/agg_group_helper.test.ts | 2 - .../components/options/basic_options.tsx | 4 +- .../components/options/color_schema.tsx | 4 +- .../components/sidebar/use_option_tabs.ts | 5 +- .../vis_default_editor/public/index.ts | 1 - .../public/vis_options_props.tsx | 22 -- .../public/markdown_options.test.tsx | 4 +- .../public/markdown_options.tsx | 4 +- .../vis_type_markdown/public/markdown_vis.ts | 7 +- .../public/settings_options.tsx | 5 +- .../vis_type_markdown/public/to_ast.ts | 3 +- .../__snapshots__/metric_vis_fn.test.ts.snap | 3 - .../public/__snapshots__/to_ast.test.ts.snap | 9 +- .../public/components/metric_vis_options.tsx | 4 +- .../vis_type_metric/public/metric_vis_fn.ts | 4 - .../vis_type_metric/public/metric_vis_type.ts | 6 +- .../vis_type_metric/public/to_ast.test.ts | 23 +- src/plugins/vis_type_metric/public/to_ast.ts | 9 +- .../public/components/table_vis_options.tsx | 10 +- .../components/table_vis_options_lazy.tsx | 5 +- .../public/legacy/table_vis_legacy_type.ts | 5 +- .../vis_type_table/public/table_vis_type.ts | 8 +- src/plugins/vis_type_table/public/to_ast.ts | 4 +- .../public/components/tag_cloud_options.tsx | 5 +- .../public/tag_cloud_type.ts | 6 +- .../vis_type_tagcloud/public/to_ast.ts | 4 +- .../public/timelion_options.tsx | 4 +- .../public/timelion_vis_type.tsx | 6 +- .../public/components/vega_vis_editor.tsx | 4 +- .../components/vega_vis_editor_lazy.tsx | 4 +- src/plugins/vis_type_vega/public/plugin.ts | 2 +- src/plugins/vis_type_vega/public/vega_type.ts | 16 +- src/plugins/vis_type_vislib/public/area.ts | 9 +- .../public/editor/components/gauge/index.tsx | 6 +- .../editor/components/heatmap/index.tsx | 4 +- .../components/heatmap/labels_panel.tsx | 5 +- .../public/editor/components/index.tsx | 11 +- .../public/editor/components/pie.tsx | 5 +- src/plugins/vis_type_vislib/public/gauge.ts | 8 +- src/plugins/vis_type_vislib/public/goal.ts | 9 +- src/plugins/vis_type_vislib/public/heatmap.ts | 7 +- .../vis_type_vislib/public/histogram.ts | 9 +- .../vis_type_vislib/public/horizontal_bar.ts | 9 +- src/plugins/vis_type_vislib/public/line.ts | 9 +- src/plugins/vis_type_vislib/public/pie.ts | 6 +- src/plugins/vis_type_vislib/public/to_ast.ts | 22 +- .../vis_type_vislib/public/to_ast_esaggs.ts | 5 +- .../public/vis_type_vislib_vis_types.ts | 5 +- .../vis_type_xy/public/editor/collections.ts | 65 +++-- .../public/editor/common_config.tsx | 6 +- .../components/common/validation_wrapper.tsx | 6 +- .../metrics_axes/category_axis_panel.tsx | 9 +- .../public/sample_vis.test.mocks.ts | 8 - .../vis_type_xy/public/types/vis_type.ts | 9 +- .../vis_type_xy/public/vis_types/area.ts | 1 + .../vis_type_xy/public/vis_types/histogram.ts | 1 + .../public/vis_types/horizontal_bar.ts | 1 + .../vis_type_xy/public/vis_types/line.ts | 1 + .../visualization_requesterror.test.js.snap | 24 -- .../public/components/_visualization.scss | 42 --- .../visualizations/public/components/index.ts | 2 - .../public/components/visualization.test.js | 92 ------- .../public/components/visualization.tsx | 73 ----- .../components/visualization_chart.test.js | 56 ---- .../public/components/visualization_chart.tsx | 134 ---------- .../visualization_requesterror.test.js | 28 -- .../components/visualization_requesterror.tsx | 51 ---- .../public/embeddable/_embeddables.scss | 4 - .../public/embeddable/get_index_pattern.ts | 25 -- .../public/embeddable/to_ast.ts | 45 ++++ .../public/embeddable/visualize_embeddable.ts | 7 +- .../visualize_embeddable_factory.tsx | 4 +- .../visualizations/public/expressions/vis.ts | 157 ----------- .../expressions/visualization_function.ts | 144 ---------- .../expressions/visualization_renderer.tsx | 51 ---- src/plugins/visualizations/public/index.ts | 27 +- .../__snapshots__/build_pipeline.test.ts.snap | 3 - .../public/legacy/build_pipeline.test.ts | 86 ------ .../public/legacy/build_pipeline.ts | 253 ------------------ src/plugins/visualizations/public/mocks.ts | 1 - src/plugins/visualizations/public/plugin.ts | 10 - src/plugins/visualizations/public/services.ts | 18 +- src/plugins/visualizations/public/types.ts | 44 +-- src/plugins/visualizations/public/vis.ts | 7 +- .../visualizations/public/vis_schemas.ts | 136 ++++++++++ .../public/vis_types/base_vis_type.test.ts | 11 +- .../public/vis_types/base_vis_type.ts | 67 +---- .../visualizations/public/vis_types/index.ts | 5 +- .../public/vis_types/react_vis_controller.tsx | 46 ---- .../public/vis_types/react_vis_type.test.ts | 36 --- .../public/vis_types/react_vis_type.ts | 35 --- .../public/vis_types/schemas.ts | 1 - .../visualizations/public/vis_types/types.ts | 80 ++++-- .../public/vis_types/types_service.ts | 26 +- .../agg_based_selection.test.tsx | 24 +- .../agg_based_selection.tsx | 6 +- .../group_selection/group_selection.test.tsx | 36 ++- .../group_selection/group_selection.tsx | 10 +- .../public/wizard/new_vis_modal.test.tsx | 25 +- .../public/wizard/new_vis_modal.tsx | 12 +- .../search_selection/search_selection.tsx | 4 +- .../snapshots/baseline/combined_test3.json | 2 +- .../snapshots/baseline/final_output_test.json | 2 +- .../snapshots/baseline/metric_all_data.json | 2 +- .../baseline/metric_invalid_data.json | 2 +- .../baseline/metric_multi_metric_data.json | 2 +- .../baseline/metric_percentage_mode.json | 2 +- .../baseline/metric_single_metric_data.json | 2 +- .../snapshots/baseline/partial_test_2.json | 2 +- .../snapshots/baseline/step_output_test3.json | 2 +- .../snapshots/session/combined_test3.json | 2 +- .../snapshots/session/final_output_test.json | 2 +- .../snapshots/session/metric_all_data.json | 2 +- .../session/metric_invalid_data.json | 2 +- .../session/metric_multi_metric_data.json | 2 +- .../session/metric_percentage_mode.json | 2 +- .../session/metric_single_metric_data.json | 2 +- .../snapshots/session/partial_test_2.json | 2 +- .../snapshots/session/step_output_test3.json | 2 +- .../kbn_tp_custom_visualizations/kibana.json | 1 + .../public/plugin.ts | 29 +- .../self_changing_components.tsx | 9 +- .../self_changing_editor.tsx | 4 +- .../public/self_changing_vis_fn.ts | 66 +++++ .../public/self_changing_vis_renderer.tsx | 26 ++ .../public/to_ast.ts | 30 +++ .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 140 files changed, 751 insertions(+), 1889 deletions(-) delete mode 100644 src/plugins/vis_default_editor/public/vis_options_props.tsx delete mode 100644 src/plugins/visualizations/public/components/__snapshots__/visualization_requesterror.test.js.snap delete mode 100644 src/plugins/visualizations/public/components/visualization.test.js delete mode 100644 src/plugins/visualizations/public/components/visualization.tsx delete mode 100644 src/plugins/visualizations/public/components/visualization_chart.test.js delete mode 100644 src/plugins/visualizations/public/components/visualization_chart.tsx delete mode 100644 src/plugins/visualizations/public/components/visualization_requesterror.test.js delete mode 100644 src/plugins/visualizations/public/components/visualization_requesterror.tsx delete mode 100644 src/plugins/visualizations/public/embeddable/get_index_pattern.ts create mode 100644 src/plugins/visualizations/public/embeddable/to_ast.ts delete mode 100644 src/plugins/visualizations/public/expressions/vis.ts delete mode 100644 src/plugins/visualizations/public/expressions/visualization_function.ts delete mode 100644 src/plugins/visualizations/public/expressions/visualization_renderer.tsx delete mode 100644 src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap delete mode 100644 src/plugins/visualizations/public/legacy/build_pipeline.test.ts delete mode 100644 src/plugins/visualizations/public/legacy/build_pipeline.ts create mode 100644 src/plugins/visualizations/public/vis_schemas.ts delete mode 100644 src/plugins/visualizations/public/vis_types/react_vis_controller.tsx delete mode 100644 src/plugins/visualizations/public/vis_types/react_vis_type.test.ts delete mode 100644 src/plugins/visualizations/public/vis_types/react_vis_type.ts create mode 100644 test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis_fn.ts create mode 100644 test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis_renderer.tsx create mode 100644 test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/to_ast.ts diff --git a/src/plugins/input_control_vis/public/components/editor/controls_tab.test.tsx b/src/plugins/input_control_vis/public/components/editor/controls_tab.test.tsx index ec9b5ee7e43da..4d82571995d58 100644 --- a/src/plugins/input_control_vis/public/components/editor/controls_tab.test.tsx +++ b/src/plugins/input_control_vis/public/components/editor/controls_tab.test.tsx @@ -29,8 +29,6 @@ beforeEach(() => { name: 'test', title: 'test', visualization: null, - requestHandler: 'test', - responseHandler: 'test', stage: 'beta', requiresSearch: false, hidden: false, diff --git a/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx b/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx index a2ae1e6851a6b..5e432d81ebefb 100644 --- a/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx +++ b/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx @@ -19,7 +19,7 @@ import { EuiSelect, } from '@elastic/eui'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { IIndexPattern } from 'src/plugins/data/public'; import { ControlEditor } from './control_editor'; import { @@ -40,7 +40,7 @@ interface ControlsTabUiState { type: CONTROL_TYPES; } -export type ControlsTabProps = VisOptionsProps & { +export type ControlsTabProps = VisEditorOptionsProps & { deps: InputControlVisDependencies; }; diff --git a/src/plugins/input_control_vis/public/components/editor/index.tsx b/src/plugins/input_control_vis/public/components/editor/index.tsx index 15b1039a8cb3c..ee457a47a3b6d 100644 --- a/src/plugins/input_control_vis/public/components/editor/index.tsx +++ b/src/plugins/input_control_vis/public/components/editor/index.tsx @@ -7,7 +7,7 @@ */ import React, { lazy } from 'react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { InputControlVisDependencies } from '../../plugin'; import { InputControlVisParams } from '../../types'; @@ -15,9 +15,9 @@ const ControlsTab = lazy(() => import('./controls_tab')); const OptionsTab = lazy(() => import('./options_tab')); export const getControlsTab = (deps: InputControlVisDependencies) => ( - props: VisOptionsProps + props: VisEditorOptionsProps ) => ; -export const OptionsTabLazy = (props: VisOptionsProps) => ( +export const OptionsTabLazy = (props: VisEditorOptionsProps) => ( ); diff --git a/src/plugins/input_control_vis/public/components/editor/options_tab.tsx b/src/plugins/input_control_vis/public/components/editor/options_tab.tsx index fa995be0840ce..9a7eaa71c3324 100644 --- a/src/plugins/input_control_vis/public/components/editor/options_tab.tsx +++ b/src/plugins/input_control_vis/public/components/editor/options_tab.tsx @@ -12,10 +12,10 @@ import { EuiForm, EuiFormRow, EuiSwitch } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiSwitchEvent } from '@elastic/eui'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { InputControlVisParams } from '../../types'; -export type OptionsTabProps = VisOptionsProps; +export type OptionsTabProps = VisEditorOptionsProps; class OptionsTab extends PureComponent { handleUpdateFiltersChange = (event: EuiSwitchEvent) => { diff --git a/src/plugins/input_control_vis/public/input_control_vis_type.ts b/src/plugins/input_control_vis/public/input_control_vis_type.ts index 8d8fdf2cfc568..00e680aa5d328 100644 --- a/src/plugins/input_control_vis/public/input_control_vis_type.ts +++ b/src/plugins/input_control_vis/public/input_control_vis_type.ts @@ -7,7 +7,7 @@ */ import { i18n } from '@kbn/i18n'; -import { VisGroups, BaseVisTypeOptions } from '../../visualizations/public'; +import { VisGroups, VisTypeDefinition } from '../../visualizations/public'; import { getControlsTab, OptionsTabLazy } from './components/editor'; import { InputControlVisDependencies } from './plugin'; import { toExpressionAst } from './to_ast'; @@ -15,7 +15,7 @@ import { InputControlVisParams } from './types'; export function createInputControlVisTypeDefinition( deps: InputControlVisDependencies -): BaseVisTypeOptions { +): VisTypeDefinition { const ControlsTab = getControlsTab(deps); return { @@ -56,7 +56,6 @@ export function createInputControlVisTypeDefinition( ], }, inspectorAdapters: {}, - requestHandler: 'none', toExpressionAst, }; } diff --git a/src/plugins/region_map/public/components/index.tsx b/src/plugins/region_map/public/components/index.tsx index 2ad3c0ffec3f4..187c36f9cc46d 100644 --- a/src/plugins/region_map/public/components/index.tsx +++ b/src/plugins/region_map/public/components/index.tsx @@ -8,11 +8,11 @@ import React, { lazy } from 'react'; import { IServiceSettings } from 'src/plugins/maps_legacy/public'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { RegionMapVisParams } from '../region_map_types'; const RegionMapOptions = lazy(() => import('./region_map_options')); export const createRegionMapOptions = (getServiceSettings: () => Promise) => ( - props: VisOptionsProps + props: VisEditorOptionsProps ) => ; diff --git a/src/plugins/region_map/public/components/region_map_options.tsx b/src/plugins/region_map/public/components/region_map_options.tsx index 0b11e1c5164d3..43bb15a547435 100644 --- a/src/plugins/region_map/public/components/region_map_options.tsx +++ b/src/plugins/region_map/public/components/region_map_options.tsx @@ -10,7 +10,7 @@ import React, { useCallback, useMemo } from 'react'; import { EuiIcon, EuiLink, EuiPanel, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { FileLayerField, VectorLayer, IServiceSettings } from '../../../maps_legacy/public'; import { SelectOption, SwitchOption, NumberInputOption } from '../../../vis_default_editor/public'; import { WmsOptions } from '../../../maps_legacy/public'; @@ -28,7 +28,7 @@ const mapFieldForOption = ({ description, name }: FileLayerField) => ({ export type RegionMapOptionsProps = { getServiceSettings: () => Promise; -} & VisOptionsProps; +} & VisEditorOptionsProps; function RegionMapOptions(props: RegionMapOptionsProps) { const { getServiceSettings, stateParams, vis, setValue } = props; diff --git a/src/plugins/region_map/public/region_map_type.ts b/src/plugins/region_map/public/region_map_type.ts index bda478389faa1..c1d46cd603f0b 100644 --- a/src/plugins/region_map/public/region_map_type.ts +++ b/src/plugins/region_map/public/region_map_type.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; -import { BaseVisTypeOptions } from '../../visualizations/public'; +import { VisTypeDefinition } from '../../visualizations/public'; import { truncatedColorSchemas } from '../../charts/public'; import { ORIGIN } from '../../maps_legacy/public'; @@ -23,7 +23,7 @@ export function createRegionMapTypeDefinition({ uiSettings, regionmapsConfig, getServiceSettings, -}: RegionMapVisualizationDependencies): BaseVisTypeOptions { +}: RegionMapVisualizationDependencies): VisTypeDefinition { return { name: 'region_map', getInfoMessage: getDeprecationMessage, @@ -139,5 +139,6 @@ provided base maps, or add your own. Darker colors represent higher values.', return vis; }, + requiresSearch: true, }; } diff --git a/src/plugins/region_map/public/to_ast.ts b/src/plugins/region_map/public/to_ast.ts index 7c81b8fa9ecbb..77aaf18f0f697 100644 --- a/src/plugins/region_map/public/to_ast.ts +++ b/src/plugins/region_map/public/to_ast.ts @@ -11,11 +11,11 @@ import { IndexPatternLoadExpressionFunctionDefinition, } from '../../data/public'; import { buildExpression, buildExpressionFunction } from '../../expressions/public'; -import { getVisSchemas, Vis, BuildPipelineParams } from '../../visualizations/public'; +import { getVisSchemas, VisToExpressionAst } from '../../visualizations/public'; import { RegionMapExpressionFunctionDefinition } from './region_map_fn'; import { RegionMapVisConfig, RegionMapVisParams } from './region_map_types'; -export const toExpressionAst = (vis: Vis, params: BuildPipelineParams) => { +export const toExpressionAst: VisToExpressionAst = (vis, params) => { const esaggs = buildExpressionFunction('esaggs', { index: buildExpression([ buildExpressionFunction('indexPatternLoad', { diff --git a/src/plugins/tile_map/public/components/tile_map_options.tsx b/src/plugins/tile_map/public/components/tile_map_options.tsx index c30d314d166bb..d6155dbfec877 100644 --- a/src/plugins/tile_map/public/components/tile_map_options.tsx +++ b/src/plugins/tile_map/public/components/tile_map_options.tsx @@ -10,8 +10,8 @@ import React, { useEffect } from 'react'; import { EuiPanel, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { - VisOptionsProps, BasicOptions, SelectOption, SwitchOption, @@ -21,7 +21,7 @@ import { WmsOptions } from '../../../maps_legacy/public'; import { TileMapVisParams } from '../types'; import { MapTypes } from '../utils/map_types'; -export type TileMapOptionsProps = VisOptionsProps; +export type TileMapOptionsProps = VisEditorOptionsProps; function TileMapOptions(props: TileMapOptionsProps) { const { stateParams, setValue, vis } = props; diff --git a/src/plugins/tile_map/public/tile_map_type.ts b/src/plugins/tile_map/public/tile_map_type.ts index 7356da0cf8bcb..ceb9c138f043c 100644 --- a/src/plugins/tile_map/public/tile_map_type.ts +++ b/src/plugins/tile_map/public/tile_map_type.ts @@ -7,7 +7,7 @@ */ import { i18n } from '@kbn/i18n'; -import { BaseVisTypeOptions } from 'src/plugins/visualizations/public'; +import { VisTypeDefinition } from 'src/plugins/visualizations/public'; import { truncatedColorSchemas } from '../../charts/public'; // @ts-expect-error @@ -21,7 +21,7 @@ import { MapTypes } from './utils/map_types'; export function createTileMapTypeDefinition( dependencies: TileMapVisualizationDependencies -): BaseVisTypeOptions { +): VisTypeDefinition { const { uiSettings, getServiceSettings } = dependencies; return { @@ -147,5 +147,6 @@ export function createTileMapTypeDefinition( } return vis; }, + requiresSearch: true, }; } diff --git a/src/plugins/tile_map/public/to_ast.ts b/src/plugins/tile_map/public/to_ast.ts index f5a964d257431..8130b7df25276 100644 --- a/src/plugins/tile_map/public/to_ast.ts +++ b/src/plugins/tile_map/public/to_ast.ts @@ -11,11 +11,11 @@ import { IndexPatternLoadExpressionFunctionDefinition, } from '../../data/public'; import { buildExpression, buildExpressionFunction } from '../../expressions/public'; -import { getVisSchemas, Vis, BuildPipelineParams } from '../../visualizations/public'; +import { getVisSchemas, VisToExpressionAst } from '../../visualizations/public'; import { TileMapExpressionFunctionDefinition } from './tile_map_fn'; import { TileMapVisConfig, TileMapVisParams } from './types'; -export const toExpressionAst = (vis: Vis, params: BuildPipelineParams) => { +export const toExpressionAst: VisToExpressionAst = (vis, params) => { const esaggs = buildExpressionFunction('esaggs', { index: buildExpression([ buildExpressionFunction('indexPatternLoad', { diff --git a/src/plugins/vis_default_editor/public/components/agg_group_helper.test.ts b/src/plugins/vis_default_editor/public/components/agg_group_helper.test.ts index 131edb4601546..fb41d610d2175 100644 --- a/src/plugins/vis_default_editor/public/components/agg_group_helper.test.ts +++ b/src/plugins/vis_default_editor/public/components/agg_group_helper.test.ts @@ -50,7 +50,6 @@ describe('DefaultEditorGroup helpers', () => { min: 0, max: 3, aggFilter: [], - editor: false, params: [], defaults: null, mustBeFirst: true, @@ -62,7 +61,6 @@ describe('DefaultEditorGroup helpers', () => { min: 2, max: 3, aggFilter: [], - editor: false, params: [], defaults: null, }, diff --git a/src/plugins/vis_default_editor/public/components/options/basic_options.tsx b/src/plugins/vis_default_editor/public/components/options/basic_options.tsx index 4edfd9982ffbd..85a94e1228a3e 100644 --- a/src/plugins/vis_default_editor/public/components/options/basic_options.tsx +++ b/src/plugins/vis_default_editor/public/components/options/basic_options.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from '../../vis_options_props'; +import { VisEditorOptionsProps } from '../../../../visualizations/public'; import { SwitchOption } from './switch'; import { SelectOption } from './select'; @@ -23,7 +23,7 @@ function BasicOptions({ stateParams, setValue, vis, -}: VisOptionsProps) { +}: VisEditorOptionsProps) { return ( <> ( interface ColorSchemaOptionsProps extends ColorSchemaParams { disabled?: boolean; colorSchemas: ColorSchema[]; - uiState: VisOptionsProps['uiState']; + uiState: VisEditorOptionsProps['uiState']; setValue: SetColorSchemaOptionsValue; showHelpText?: boolean; } diff --git a/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts b/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts index fbec23fd199f5..be0e4dd9a8c20 100644 --- a/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts +++ b/src/plugins/vis_default_editor/public/components/sidebar/use_option_tabs.ts @@ -9,13 +9,12 @@ import { useCallback, useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { Vis } from '../../../../visualizations/public'; +import { Vis, VisEditorOptionsProps } from '../../../../visualizations/public'; -import { VisOptionsProps } from '../../vis_options_props'; import { DefaultEditorDataTab, DefaultEditorDataTabProps } from './data_tab'; export interface OptionTab { - editor: React.ComponentType; + editor: React.ComponentType; name: string; title: string; isSelected?: boolean; diff --git a/src/plugins/vis_default_editor/public/index.ts b/src/plugins/vis_default_editor/public/index.ts index a4c94dd664968..9d315f1a94ce7 100644 --- a/src/plugins/vis_default_editor/public/index.ts +++ b/src/plugins/vis_default_editor/public/index.ts @@ -16,7 +16,6 @@ export { PalettePicker } from './components/controls/palette_picker'; export * from './components/options'; export { RangesParamEditor, RangeValues } from './components/controls/ranges'; export * from './editor_size'; -export * from './vis_options_props'; export * from './utils'; export const plugin = (context: PluginInitializerContext) => { diff --git a/src/plugins/vis_default_editor/public/vis_options_props.tsx b/src/plugins/vis_default_editor/public/vis_options_props.tsx deleted file mode 100644 index 6180686b6996d..0000000000000 --- a/src/plugins/vis_default_editor/public/vis_options_props.tsx +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { Vis, PersistedState } from 'src/plugins/visualizations/public'; -import { IAggConfigs } from 'src/plugins/data/public'; - -export interface VisOptionsProps { - aggs: IAggConfigs; - hasHistogramAgg: boolean; - isTabSelected: boolean; - stateParams: VisParamType; - vis: Vis; - uiState: PersistedState; - setValue(paramName: T, value: VisParamType[T]): void; - setValidity(isValid: boolean): void; - setTouched(isTouched: boolean): void; -} diff --git a/src/plugins/vis_type_markdown/public/markdown_options.test.tsx b/src/plugins/vis_type_markdown/public/markdown_options.test.tsx index cf27118ac71e4..9d464cf9e2063 100644 --- a/src/plugins/vis_type_markdown/public/markdown_options.test.tsx +++ b/src/plugins/vis_type_markdown/public/markdown_options.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { MarkdownVisParams } from './types'; import { MarkdownOptions } from './markdown_options'; @@ -21,7 +21,7 @@ describe('MarkdownOptions', () => { openLinksInNewTab: false, }, setValue: jest.fn(), - } as unknown) as VisOptionsProps; + } as unknown) as VisEditorOptionsProps; it('should match snapshot', () => { const comp = shallow(); diff --git a/src/plugins/vis_type_markdown/public/markdown_options.tsx b/src/plugins/vis_type_markdown/public/markdown_options.tsx index 72e4aaf8758b2..79d850b8c1fd8 100644 --- a/src/plugins/vis_type_markdown/public/markdown_options.tsx +++ b/src/plugins/vis_type_markdown/public/markdown_options.tsx @@ -18,10 +18,10 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { MarkdownVisParams } from './types'; -function MarkdownOptions({ stateParams, setValue }: VisOptionsProps) { +function MarkdownOptions({ stateParams, setValue }: VisEditorOptionsProps) { const onMarkdownUpdate = useCallback( ({ target: { value } }: React.ChangeEvent) => setValue('markdown', value), [setValue] diff --git a/src/plugins/vis_type_markdown/public/markdown_vis.ts b/src/plugins/vis_type_markdown/public/markdown_vis.ts index e698316dc8e70..adfdb811cc28c 100644 --- a/src/plugins/vis_type_markdown/public/markdown_vis.ts +++ b/src/plugins/vis_type_markdown/public/markdown_vis.ts @@ -11,10 +11,11 @@ import { i18n } from '@kbn/i18n'; import { MarkdownOptions } from './markdown_options'; import { SettingsOptions } from './settings_options_lazy'; import { DefaultEditorSize } from '../../vis_default_editor/public'; -import { VisGroups } from '../../visualizations/public'; +import { VisGroups, VisTypeDefinition } from '../../visualizations/public'; import { toExpressionAst } from './to_ast'; +import { MarkdownVisParams } from './types'; -export const markdownVisDefinition = { +export const markdownVisDefinition: VisTypeDefinition = { name: 'markdown', title: 'Markdown', isAccessible: true, @@ -58,7 +59,5 @@ export const markdownVisDefinition = { showTimePicker: false, showFilterBar: false, }, - requestHandler: 'none', - responseHandler: 'none', inspectorAdapters: {}, }; diff --git a/src/plugins/vis_type_markdown/public/settings_options.tsx b/src/plugins/vis_type_markdown/public/settings_options.tsx index 4ebcc88a8c04f..c18f1305d778a 100644 --- a/src/plugins/vis_type_markdown/public/settings_options.tsx +++ b/src/plugins/vis_type_markdown/public/settings_options.tsx @@ -10,10 +10,11 @@ import React from 'react'; import { EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps, SwitchOption, RangeOption } from '../../vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; +import { SwitchOption, RangeOption } from '../../vis_default_editor/public'; import { MarkdownVisParams } from './types'; -function SettingsOptions({ stateParams, setValue }: VisOptionsProps) { +function SettingsOptions({ stateParams, setValue }: VisEditorOptionsProps) { return ( { +export const toExpressionAst: VisToExpressionAst = (vis) => { const { markdown, fontSize, openLinksInNewTab } = vis.params; const markdownVis = buildExpressionFunction( diff --git a/src/plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap b/src/plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap index fd8f3a712d8ae..a212cec2d8827 100644 --- a/src/plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap +++ b/src/plugins/vis_type_metric/public/__snapshots__/metric_vis_fn.test.ts.snap @@ -5,9 +5,6 @@ Object { "as": "metric_vis", "type": "render", "value": Object { - "params": Object { - "listenOnChange": true, - }, "visConfig": Object { "dimensions": Object { "metrics": undefined, diff --git a/src/plugins/vis_type_metric/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_type_metric/public/__snapshots__/to_ast.test.ts.snap index a89f41737d7bc..46e86c4c25de1 100644 --- a/src/plugins/vis_type_metric/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_type_metric/public/__snapshots__/to_ast.test.ts.snap @@ -37,6 +37,9 @@ Object { "percentageMode": Array [ true, ], + "showLabels": Array [ + false, + ], }, "function": "metricVis", "type": "function", @@ -79,7 +82,11 @@ Object { "type": "function", }, Object { - "arguments": Object {}, + "arguments": Object { + "showLabels": Array [ + false, + ], + }, "function": "metricVis", "type": "function", }, diff --git a/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx b/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx index c8448ae68c074..069690b58e2a0 100644 --- a/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx +++ b/src/plugins/vis_type_metric/public/components/metric_vis_options.tsx @@ -18,10 +18,10 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { ColorRanges, SetColorRangeValue, - VisOptionsProps, SwitchOption, SetColorSchemaOptionsValue, ColorSchemaOptions, @@ -37,7 +37,7 @@ function MetricVisOptions({ setTouched, vis, uiState, -}: VisOptionsProps) { +}: VisEditorOptionsProps) { const setMetricValue: ( paramName: T, value: MetricVisParam[T] diff --git a/src/plugins/vis_type_metric/public/metric_vis_fn.ts b/src/plugins/vis_type_metric/public/metric_vis_fn.ts index 892523493fb78..083d0413161b2 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_fn.ts +++ b/src/plugins/vis_type_metric/public/metric_vis_fn.ts @@ -39,7 +39,6 @@ export interface MetricVisRenderValue { visType: typeof visType; visData: Input; visConfig: Pick; - params: any; } export type MetricVisExpressionFunctionDefinition = ExpressionFunctionDefinition< @@ -194,9 +193,6 @@ export const createMetricVisFn = (): MetricVisExpressionFunctionDefinition => ({ }, dimensions, }, - params: { - listenOnChange: true, - }, }, }; }, diff --git a/src/plugins/vis_type_metric/public/metric_vis_type.ts b/src/plugins/vis_type_metric/public/metric_vis_type.ts index cd4357574950d..e81d8f071c4f0 100644 --- a/src/plugins/vis_type_metric/public/metric_vis_type.ts +++ b/src/plugins/vis_type_metric/public/metric_vis_type.ts @@ -9,11 +9,12 @@ import { i18n } from '@kbn/i18n'; import { MetricVisOptions } from './components/metric_vis_options'; import { ColorSchemas, colorSchemas, ColorMode } from '../../charts/public'; -import { BaseVisTypeOptions } from '../../visualizations/public'; +import { VisTypeDefinition } from '../../visualizations/public'; import { AggGroupNames } from '../../data/public'; import { toExpressionAst } from './to_ast'; +import { VisParams } from './types'; -export const createMetricVisTypeDefinition = (): BaseVisTypeOptions => ({ +export const createMetricVisTypeDefinition = (): VisTypeDefinition => ({ name: 'metric', title: i18n.translate('visTypeMetric.metricTitle', { defaultMessage: 'Metric' }), icon: 'visMetric', @@ -110,4 +111,5 @@ export const createMetricVisTypeDefinition = (): BaseVisTypeOptions => ({ }, ], }, + requiresSearch: true, }); diff --git a/src/plugins/vis_type_metric/public/to_ast.test.ts b/src/plugins/vis_type_metric/public/to_ast.test.ts index fb90b27391c83..871b2ca0dc379 100644 --- a/src/plugins/vis_type_metric/public/to_ast.test.ts +++ b/src/plugins/vis_type_metric/public/to_ast.test.ts @@ -6,14 +6,17 @@ * Public License, v 1. */ +import { TimefilterContract } from 'src/plugins/data/public'; +import { Vis } from 'src/plugins/visualizations/public'; + import { toExpressionAst } from './to_ast'; -import { Vis } from '../../visualizations/public'; +import { VisParams } from './types'; describe('metric vis toExpressionAst function', () => { - let vis: Vis; + let vis: Vis; beforeEach(() => { - vis = { + vis = ({ isHierarchical: () => false, type: {}, params: { @@ -26,18 +29,22 @@ describe('metric vis toExpressionAst function', () => { aggs: [], } as any, }, - } as any; + } as unknown) as Vis; }); it('without params', () => { - vis.params = { metric: {} }; - const actual = toExpressionAst(vis, {}); + vis.params = { metric: {} } as VisParams; + const actual = toExpressionAst(vis, { + timefilter: {} as TimefilterContract, + }); expect(actual).toMatchSnapshot(); }); it('with percentage mode should have percentage format', () => { - vis.params = { metric: { percentageMode: true } }; - const actual = toExpressionAst(vis, {}); + vis.params = { metric: { percentageMode: true } } as VisParams; + const actual = toExpressionAst(vis, { + timefilter: {} as TimefilterContract, + }); expect(actual).toMatchSnapshot(); }); }); diff --git a/src/plugins/vis_type_metric/public/to_ast.ts b/src/plugins/vis_type_metric/public/to_ast.ts index 3b95b0c841016..3addce7610f2e 100644 --- a/src/plugins/vis_type_metric/public/to_ast.ts +++ b/src/plugins/vis_type_metric/public/to_ast.ts @@ -7,13 +7,14 @@ */ import { get } from 'lodash'; -import { getVisSchemas, SchemaConfig, Vis } from '../../visualizations/public'; +import { getVisSchemas, SchemaConfig, VisToExpressionAst } from '../../visualizations/public'; import { buildExpression, buildExpressionFunction } from '../../expressions/public'; import { MetricVisExpressionFunctionDefinition } from './metric_vis_fn'; import { EsaggsExpressionFunctionDefinition, IndexPatternLoadExpressionFunctionDefinition, } from '../../data/public'; +import { VisParams } from './types'; const prepareDimension = (params: SchemaConfig) => { const visdimension = buildExpressionFunction('visdimension', { accessor: params.accessor }); @@ -26,7 +27,7 @@ const prepareDimension = (params: SchemaConfig) => { return buildExpression([visdimension]); }; -export const toExpressionAst = (vis: Vis, params: any) => { +export const toExpressionAst: VisToExpressionAst = (vis, params) => { const esaggs = buildExpressionFunction('esaggs', { index: buildExpression([ buildExpressionFunction('indexPatternLoad', { @@ -34,7 +35,7 @@ export const toExpressionAst = (vis: Vis, params: any) => { }), ]), metricsAtAllLevels: vis.isHierarchical(), - partialRows: vis.params.showPartialRows || false, + partialRows: false, aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), }); @@ -65,7 +66,7 @@ export const toExpressionAst = (vis: Vis, params: any) => { colorMode: metricColorMode, useRanges, invertColors, - showLabels: labels && labels.show, + showLabels: labels?.show ?? false, }); if (style) { diff --git a/src/plugins/vis_type_table/public/components/table_vis_options.tsx b/src/plugins/vis_type_table/public/components/table_vis_options.tsx index a70ecb43f1be7..163dae7ddc1c6 100644 --- a/src/plugins/vis_type_table/public/components/table_vis_options.tsx +++ b/src/plugins/vis_type_table/public/components/table_vis_options.tsx @@ -12,13 +12,9 @@ import { EuiIconTip, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { search } from '../../../data/public'; -import { - SwitchOption, - SelectOption, - NumberInputOption, - VisOptionsProps, -} from '../../../vis_default_editor/public'; +import { SwitchOption, SelectOption, NumberInputOption } from '../../../vis_default_editor/public'; import { TableVisParams } from '../../common'; import { totalAggregations } from './utils'; @@ -29,7 +25,7 @@ function TableOptions({ stateParams, setValidity, setValue, -}: VisOptionsProps) { +}: VisEditorOptionsProps) { const percentageColumns = useMemo( () => [ { diff --git a/src/plugins/vis_type_table/public/components/table_vis_options_lazy.tsx b/src/plugins/vis_type_table/public/components/table_vis_options_lazy.tsx index 716b77e9c91d2..2f7369996634a 100644 --- a/src/plugins/vis_type_table/public/components/table_vis_options_lazy.tsx +++ b/src/plugins/vis_type_table/public/components/table_vis_options_lazy.tsx @@ -8,12 +8,13 @@ import React, { lazy, Suspense } from 'react'; import { EuiLoadingSpinner } from '@elastic/eui'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; + +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { TableVisParams } from '../../common'; const TableOptionsComponent = lazy(() => import('./table_vis_options')); -export const TableOptions = (props: VisOptionsProps) => ( +export const TableOptions = (props: VisEditorOptionsProps) => ( }> diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_type.ts b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_type.ts index 3e1140275593d..53ad67ab4dd94 100644 --- a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_type.ts +++ b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_type.ts @@ -8,14 +8,14 @@ import { i18n } from '@kbn/i18n'; import { AggGroupNames } from '../../../data/public'; -import { BaseVisTypeOptions } from '../../../visualizations/public'; +import { VisTypeDefinition } from '../../../visualizations/public'; import { TableOptions } from '../components/table_vis_options_lazy'; import { VIS_EVENT_TO_TRIGGER } from '../../../visualizations/public'; import { TableVisParams, VIS_TYPE_TABLE } from '../../common'; import { toExpressionAst } from '../to_ast'; -export const tableVisLegacyTypeDefinition: BaseVisTypeOptions = { +export const tableVisLegacyTypeDefinition: VisTypeDefinition = { name: VIS_TYPE_TABLE, title: i18n.translate('visTypeTable.tableVisTitle', { defaultMessage: 'Data table', @@ -81,4 +81,5 @@ export const tableVisLegacyTypeDefinition: BaseVisTypeOptions = }, toExpressionAst, hierarchicalData: (vis) => vis.params.showPartialRows || vis.params.showMetricsAtAllLevels, + requiresSearch: true, }; diff --git a/src/plugins/vis_type_table/public/table_vis_type.ts b/src/plugins/vis_type_table/public/table_vis_type.ts index ef6d85db103b3..92148a5f085b0 100644 --- a/src/plugins/vis_type_table/public/table_vis_type.ts +++ b/src/plugins/vis_type_table/public/table_vis_type.ts @@ -7,15 +7,14 @@ */ import { i18n } from '@kbn/i18n'; -import { AggGroupNames } from '../../data/public'; -import { BaseVisTypeOptions } from '../../visualizations/public'; +import { AggGroupNames } from '../../data/public'; +import { VIS_EVENT_TO_TRIGGER, VisTypeDefinition } from '../../visualizations/public'; import { TableVisParams, VIS_TYPE_TABLE } from '../common'; import { TableOptions } from './components/table_vis_options_lazy'; -import { VIS_EVENT_TO_TRIGGER } from '../../../plugins/visualizations/public'; import { toExpressionAst } from './to_ast'; -export const tableVisTypeDefinition: BaseVisTypeOptions = { +export const tableVisTypeDefinition: VisTypeDefinition = { name: VIS_TYPE_TABLE, title: i18n.translate('visTypeTable.tableVisTitle', { defaultMessage: 'Data table', @@ -78,4 +77,5 @@ export const tableVisTypeDefinition: BaseVisTypeOptions = { }, toExpressionAst, hierarchicalData: (vis) => vis.params.showPartialRows || vis.params.showMetricsAtAllLevels, + requiresSearch: true, }; diff --git a/src/plugins/vis_type_table/public/to_ast.ts b/src/plugins/vis_type_table/public/to_ast.ts index 1cbe9832e4c98..ba79d82947d06 100644 --- a/src/plugins/vis_type_table/public/to_ast.ts +++ b/src/plugins/vis_type_table/public/to_ast.ts @@ -11,7 +11,7 @@ import { IndexPatternLoadExpressionFunctionDefinition, } from '../../data/public'; import { buildExpression, buildExpressionFunction } from '../../expressions/public'; -import { getVisSchemas, Vis, BuildPipelineParams } from '../../visualizations/public'; +import { getVisSchemas, VisToExpressionAst } from '../../visualizations/public'; import { TableVisParams } from '../common'; import { TableExpressionFunctionDefinition } from './table_vis_fn'; import { TableVisConfig } from './types'; @@ -41,7 +41,7 @@ const buildTableVisConfig = ( return visConfig; }; -export const toExpressionAst = (vis: Vis, params: BuildPipelineParams) => { +export const toExpressionAst: VisToExpressionAst = (vis, params) => { const esaggs = buildExpressionFunction('esaggs', { index: buildExpression([ buildExpressionFunction('indexPatternLoad', { diff --git a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx index 2bcae41fae566..d15772b3fdb18 100644 --- a/src/plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx +++ b/src/plugins/vis_type_tagcloud/public/components/tag_cloud_options.tsx @@ -9,11 +9,12 @@ import React from 'react'; import { EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps, SelectOption, SwitchOption } from '../../../vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; +import { SelectOption, SwitchOption } from '../../../vis_default_editor/public'; import { ValidatedDualRange } from '../../../kibana_react/public'; import { TagCloudVisParams } from '../types'; -function TagCloudOptions({ stateParams, setValue, vis }: VisOptionsProps) { +function TagCloudOptions({ stateParams, setValue, vis }: VisEditorOptionsProps) { const handleFontSizeChange = ([minFontSize, maxFontSize]: [string | number, string | number]) => { setValue('minFontSize', Number(minFontSize)); setValue('maxFontSize', Number(maxFontSize)); diff --git a/src/plugins/vis_type_tagcloud/public/tag_cloud_type.ts b/src/plugins/vis_type_tagcloud/public/tag_cloud_type.ts index 8159192b3491a..ebfa8db41944c 100644 --- a/src/plugins/vis_type_tagcloud/public/tag_cloud_type.ts +++ b/src/plugins/vis_type_tagcloud/public/tag_cloud_type.ts @@ -7,6 +7,7 @@ */ import { i18n } from '@kbn/i18n'; +import { AggGroupNames } from '../../data/public'; import { VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; import { TagCloudOptions } from './components/tag_cloud_options'; @@ -78,7 +79,7 @@ export const tagCloudVisTypeDefinition = { optionsTemplate: TagCloudOptions, schemas: [ { - group: 'metrics', + group: AggGroupNames.Metrics, name: 'metric', title: i18n.translate('visTypeTagCloud.vis.schemas.metricTitle', { defaultMessage: 'Tag size', @@ -96,7 +97,7 @@ export const tagCloudVisTypeDefinition = { defaults: [{ schema: 'metric', type: 'count' }], }, { - group: 'buckets', + group: AggGroupNames.Buckets, name: 'segment', title: i18n.translate('visTypeTagCloud.vis.schemas.segmentTitle', { defaultMessage: 'Tags', @@ -107,4 +108,5 @@ export const tagCloudVisTypeDefinition = { }, ], }, + requiresSearch: true, }; diff --git a/src/plugins/vis_type_tagcloud/public/to_ast.ts b/src/plugins/vis_type_tagcloud/public/to_ast.ts index adde82dd0dda9..1d9b24235b7ff 100644 --- a/src/plugins/vis_type_tagcloud/public/to_ast.ts +++ b/src/plugins/vis_type_tagcloud/public/to_ast.ts @@ -11,7 +11,7 @@ import { IndexPatternLoadExpressionFunctionDefinition, } from '../../data/public'; import { buildExpression, buildExpressionFunction } from '../../expressions/public'; -import { getVisSchemas, SchemaConfig, Vis, BuildPipelineParams } from '../../visualizations/public'; +import { getVisSchemas, SchemaConfig, VisToExpressionAst } from '../../visualizations/public'; import { TagcloudExpressionFunctionDefinition } from './tag_cloud_fn'; import { TagCloudVisParams } from './types'; @@ -26,7 +26,7 @@ const prepareDimension = (params: SchemaConfig) => { return buildExpression([visdimension]); }; -export const toExpressionAst = (vis: Vis, params: BuildPipelineParams) => { +export const toExpressionAst: VisToExpressionAst = (vis, params) => { const esaggs = buildExpressionFunction('esaggs', { index: buildExpression([ buildExpressionFunction('indexPatternLoad', { diff --git a/src/plugins/vis_type_timelion/public/timelion_options.tsx b/src/plugins/vis_type_timelion/public/timelion_options.tsx index 4627a5d5c8657..e366ec98f4be0 100644 --- a/src/plugins/vis_type_timelion/public/timelion_options.tsx +++ b/src/plugins/vis_type_timelion/public/timelion_options.tsx @@ -9,7 +9,7 @@ import React, { useCallback } from 'react'; import { EuiPanel } from '@elastic/eui'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { KibanaContextProvider } from '../../kibana_react/public'; import { TimelionVisParams } from './timelion_vis_fn'; @@ -18,7 +18,7 @@ import { TimelionVisDependencies } from './plugin'; import './timelion_options.scss'; -export type TimelionOptionsProps = VisOptionsProps; +export type TimelionOptionsProps = VisEditorOptionsProps; function TimelionOptions({ services, diff --git a/src/plugins/vis_type_timelion/public/timelion_vis_type.tsx b/src/plugins/vis_type_timelion/public/timelion_vis_type.tsx index 21344fc794c98..c9780ec6bcd1c 100644 --- a/src/plugins/vis_type_timelion/public/timelion_vis_type.tsx +++ b/src/plugins/vis_type_timelion/public/timelion_vis_type.tsx @@ -10,7 +10,6 @@ import React, { lazy } from 'react'; import { i18n } from '@kbn/i18n'; import { DefaultEditorSize } from '../../vis_default_editor/public'; -import { getTimelionRequestHandler } from './helpers/timelion_request_handler'; import { TimelionOptionsProps } from './timelion_options'; import { TimelionVisDependencies } from './plugin'; import { toExpressionAst } from './to_ast'; @@ -22,8 +21,6 @@ const TimelionOptions = lazy(() => import('./timelion_options')); export const TIMELION_VIS_NAME = 'timelion'; export function getTimelionVisDefinition(dependencies: TimelionVisDependencies) { - const timelionRequestHandler = getTimelionRequestHandler(dependencies); - // return the visType object, which kibana will use to display and configure new // Vis object of this type. return { @@ -45,9 +42,7 @@ export function getTimelionVisDefinition(dependencies: TimelionVisDependencies) ), defaultSize: DefaultEditorSize.MEDIUM, }, - requestHandler: timelionRequestHandler, toExpressionAst, - responseHandler: 'none', inspectorAdapters: {}, getSupportedTriggers: () => { return [VIS_EVENT_TO_TRIGGER.applyFilter]; @@ -57,5 +52,6 @@ export function getTimelionVisDefinition(dependencies: TimelionVisDependencies) showQueryBar: false, showFilterBar: false, }, + requiresSearch: true, }; } diff --git a/src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx b/src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx index 7afc01adec385..0a54a74b6b68c 100644 --- a/src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx +++ b/src/plugins/vis_type_vega/public/components/vega_vis_editor.tsx @@ -13,7 +13,7 @@ import hjson from 'hjson'; import 'brace/mode/hjson'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { getNotifications } from '../services'; import { VisParams } from '../vega_fn'; import { VegaHelpMenu } from './vega_help_menu'; @@ -55,7 +55,7 @@ function format( } } -function VegaVisEditor({ stateParams, setValue }: VisOptionsProps) { +function VegaVisEditor({ stateParams, setValue }: VisEditorOptionsProps) { const onChange = useCallback( (value: string) => { setValue('spec', value); diff --git a/src/plugins/vis_type_vega/public/components/vega_vis_editor_lazy.tsx b/src/plugins/vis_type_vega/public/components/vega_vis_editor_lazy.tsx index 875f13453cf6d..bd26424552038 100644 --- a/src/plugins/vis_type_vega/public/components/vega_vis_editor_lazy.tsx +++ b/src/plugins/vis_type_vega/public/components/vega_vis_editor_lazy.tsx @@ -8,11 +8,11 @@ import React, { lazy } from 'react'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { VisParams } from '../vega_fn'; const VegaVisEditor = lazy(() => import('./vega_vis_editor')); -export const VegaVisEditorComponent = (props: VisOptionsProps) => ( +export const VegaVisEditorComponent = (props: VisEditorOptionsProps) => ( ); diff --git a/src/plugins/vis_type_vega/public/plugin.ts b/src/plugins/vis_type_vega/public/plugin.ts index b74b686500e6d..376ef84de23c3 100644 --- a/src/plugins/vis_type_vega/public/plugin.ts +++ b/src/plugins/vis_type_vega/public/plugin.ts @@ -84,7 +84,7 @@ export class VegaPlugin implements Plugin, void> { expressions.registerFunction(() => createVegaFn(visualizationDependencies)); expressions.registerRenderer(getVegaVisRenderer(visualizationDependencies)); - visualizations.createBaseVisualization(createVegaTypeDefinition(visualizationDependencies)); + visualizations.createBaseVisualization(createVegaTypeDefinition()); } public start(core: CoreStart, { data }: VegaPluginStartDependencies) { diff --git a/src/plugins/vis_type_vega/public/vega_type.ts b/src/plugins/vis_type_vega/public/vega_type.ts index 66e4b8b98056f..4b2ec65850030 100644 --- a/src/plugins/vis_type_vega/public/vega_type.ts +++ b/src/plugins/vis_type_vega/public/vega_type.ts @@ -8,16 +8,13 @@ import { i18n } from '@kbn/i18n'; import { parse } from 'hjson'; -import type { BaseVisTypeOptions } from 'src/plugins/visualizations/public'; import { DefaultEditorSize } from '../../vis_default_editor/public'; -import type { VegaVisualizationDependencies } from './plugin'; +import { VIS_EVENT_TO_TRIGGER, VisGroups, VisTypeDefinition } from '../../visualizations/public'; -import { createVegaRequestHandler } from './vega_request_handler'; import { getDefaultSpec } from './default_spec'; import { extractIndexPatternsFromSpec } from './lib/extract_index_pattern'; import { createInspectorAdapters } from './vega_inspector'; -import { VIS_EVENT_TO_TRIGGER, VisGroups } from '../../visualizations/public'; import { toExpressionAst } from './to_ast'; import { getInfoMessage } from './components/experimental_map_vis_info'; import { VegaVisEditorComponent } from './components/vega_vis_editor_lazy'; @@ -25,11 +22,7 @@ import { VegaVisEditorComponent } from './components/vega_vis_editor_lazy'; import type { VegaSpec } from './data_model/types'; import type { VisParams } from './vega_fn'; -export const createVegaTypeDefinition = ( - dependencies: VegaVisualizationDependencies -): BaseVisTypeOptions => { - const requestHandler = createVegaRequestHandler(dependencies); - +export const createVegaTypeDefinition = (): VisTypeDefinition => { return { name: 'vega', title: 'Vega', @@ -52,7 +45,6 @@ export const createVegaTypeDefinition = ( enableAutoApply: true, defaultSize: DefaultEditorSize.MEDIUM, }, - requestHandler, toExpressionAst, options: { showIndexSelection: false, @@ -73,5 +65,9 @@ export const createVegaTypeDefinition = ( return []; }, inspectorAdapters: createInspectorAdapters, + /** + * This is necessary for showing actions bar in top of vega editor + */ + requiresSearch: true, }; }; diff --git a/src/plugins/vis_type_vislib/public/area.ts b/src/plugins/vis_type_vislib/public/area.ts index 7458d0a44ecae..cbb705f4cce5d 100644 --- a/src/plugins/vis_type_vislib/public/area.ts +++ b/src/plugins/vis_type_vislib/public/area.ts @@ -7,13 +7,12 @@ */ import { xyVisTypes } from '../../vis_type_xy/public'; -import { BaseVisTypeOptions } from '../../visualizations/public'; +import { VisTypeDefinition } from '../../visualizations/public'; import { toExpressionAst } from './to_ast'; import { BasicVislibParams } from './types'; -export const areaVisTypeDefinition: BaseVisTypeOptions = { - ...(xyVisTypes.area() as BaseVisTypeOptions), +export const areaVisTypeDefinition = { + ...xyVisTypes.area(), toExpressionAst, - visualization: undefined, -}; +} as VisTypeDefinition; diff --git a/src/plugins/vis_type_vislib/public/editor/components/gauge/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/gauge/index.tsx index fa0091b2082b7..e9651954ed302 100644 --- a/src/plugins/vis_type_vislib/public/editor/components/gauge/index.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/gauge/index.tsx @@ -9,20 +9,20 @@ import React, { useCallback } from 'react'; import { EuiSpacer } from '@elastic/eui'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { GaugeVisParams } from '../../../gauge'; import { RangesPanel } from './ranges_panel'; import { StylePanel } from './style_panel'; import { LabelsPanel } from './labels_panel'; -export type GaugeOptionsInternalProps = VisOptionsProps & { +export type GaugeOptionsInternalProps = VisEditorOptionsProps & { setGaugeValue: ( paramName: T, value: GaugeVisParams['gauge'][T] ) => void; }; -function GaugeOptions(props: VisOptionsProps) { +function GaugeOptions(props: VisEditorOptionsProps) { const { stateParams, setValue } = props; const setGaugeValue: GaugeOptionsInternalProps['setGaugeValue'] = useCallback( diff --git a/src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx index 7092615d9fcaf..2dd4b06a52288 100644 --- a/src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/heatmap/index.tsx @@ -12,9 +12,9 @@ import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { ValueAxis } from '../../../../../vis_type_xy/public'; import { - VisOptionsProps, BasicOptions, SelectOption, SwitchOption, @@ -28,7 +28,7 @@ import { import { HeatmapVisParams } from '../../../heatmap'; import { LabelsPanel } from './labels_panel'; -function HeatmapOptions(props: VisOptionsProps) { +function HeatmapOptions(props: VisEditorOptionsProps) { const { stateParams, vis, uiState, setValue, setValidity, setTouched } = props; const [valueAxis] = stateParams.valueAxes; const isColorsNumberInvalid = stateParams.colorsNumber < 2 || stateParams.colorsNumber > 10; diff --git a/src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx b/src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx index cc224f8e1c6aa..ff98a494ad906 100644 --- a/src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/heatmap/labels_panel.tsx @@ -12,7 +12,8 @@ import { EuiColorPicker, EuiFormRow, EuiPanel, EuiSpacer, EuiTitle } from '@elas import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { VisOptionsProps, SwitchOption } from '../../../../../vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; +import { SwitchOption } from '../../../../../vis_default_editor/public'; import { ValueAxis } from '../../../../../vis_type_xy/public'; import { HeatmapVisParams } from '../../../heatmap'; @@ -21,7 +22,7 @@ const VERTICAL_ROTATION = 270; interface LabelsPanelProps { valueAxis: ValueAxis; - setValue: VisOptionsProps['setValue']; + setValue: VisEditorOptionsProps['setValue']; } function LabelsPanel({ valueAxis, setValue }: LabelsPanelProps) { diff --git a/src/plugins/vis_type_vislib/public/editor/components/index.tsx b/src/plugins/vis_type_vislib/public/editor/components/index.tsx index 264c3066f13fe..6c6181246d6db 100644 --- a/src/plugins/vis_type_vislib/public/editor/components/index.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/index.tsx @@ -8,8 +8,7 @@ import React, { lazy } from 'react'; -import { VisOptionsProps } from '../../../../vis_default_editor/public'; - +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; import { GaugeVisParams } from '../../gauge'; import { PieVisParams } from '../../pie'; import { HeatmapVisParams } from '../../heatmap'; @@ -18,12 +17,14 @@ const GaugeOptionsLazy = lazy(() => import('./gauge')); const PieOptionsLazy = lazy(() => import('./pie')); const HeatmapOptionsLazy = lazy(() => import('./heatmap')); -export const GaugeOptions = (props: VisOptionsProps) => ( +export const GaugeOptions = (props: VisEditorOptionsProps) => ( ); -export const PieOptions = (props: VisOptionsProps) => ; +export const PieOptions = (props: VisEditorOptionsProps) => ( + +); -export const HeatmapOptions = (props: VisOptionsProps) => ( +export const HeatmapOptions = (props: VisEditorOptionsProps) => ( ); diff --git a/src/plugins/vis_type_vislib/public/editor/components/pie.tsx b/src/plugins/vis_type_vislib/public/editor/components/pie.tsx index 863b11c6a3fcf..e0ea1fcee4881 100644 --- a/src/plugins/vis_type_vislib/public/editor/components/pie.tsx +++ b/src/plugins/vis_type_vislib/public/editor/components/pie.tsx @@ -12,12 +12,13 @@ import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { BasicOptions, SwitchOption, VisOptionsProps } from '../../../../vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; +import { BasicOptions, SwitchOption } from '../../../../vis_default_editor/public'; import { TruncateLabelsOption } from '../../../../vis_type_xy/public'; import { PieVisParams } from '../../pie'; -function PieOptions(props: VisOptionsProps) { +function PieOptions(props: VisEditorOptionsProps) { const { stateParams, setValue } = props; const setLabels = ( paramName: T, diff --git a/src/plugins/vis_type_vislib/public/gauge.ts b/src/plugins/vis_type_vislib/public/gauge.ts index 5dc59f62edffd..e0c63fd15e3d7 100644 --- a/src/plugins/vis_type_vislib/public/gauge.ts +++ b/src/plugins/vis_type_vislib/public/gauge.ts @@ -11,9 +11,9 @@ import { i18n } from '@kbn/i18n'; import { ColorMode, ColorSchemas, ColorSchemaParams, Labels, Style } from '../../charts/public'; import { RangeValues } from '../../vis_default_editor/public'; import { AggGroupNames } from '../../data/public'; -import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; +import { VisTypeDefinition, VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; -import { Alignment, GaugeType, BasicVislibParams, VislibChartType } from './types'; +import { Alignment, GaugeType, VislibChartType } from './types'; import { getGaugeCollections } from './editor'; import { toExpressionAst } from './to_ast'; import { GaugeOptions } from './editor/components'; @@ -46,7 +46,7 @@ export interface GaugeVisParams { gauge: Gauge; } -export const gaugeVisTypeDefinition: BaseVisTypeOptions = { +export const gaugeVisTypeDefinition: VisTypeDefinition = { name: 'gauge', title: i18n.translate('visTypeVislib.gauge.gaugeTitle', { defaultMessage: 'Gauge' }), icon: 'visGauge', @@ -135,5 +135,5 @@ export const gaugeVisTypeDefinition: BaseVisTypeOptions = { }, ], }, - useCustomNoDataScreen: true, + requiresSearch: true, }; diff --git a/src/plugins/vis_type_vislib/public/goal.ts b/src/plugins/vis_type_vislib/public/goal.ts index 55a9f83daa4ab..6565ae53f3104 100644 --- a/src/plugins/vis_type_vislib/public/goal.ts +++ b/src/plugins/vis_type_vislib/public/goal.ts @@ -10,13 +10,14 @@ import { i18n } from '@kbn/i18n'; import { AggGroupNames } from '../../data/public'; import { ColorMode, ColorSchemas } from '../../charts/public'; -import { BaseVisTypeOptions } from '../../visualizations/public'; +import { VisTypeDefinition } from '../../visualizations/public'; import { getGaugeCollections, GaugeOptions } from './editor'; import { toExpressionAst } from './to_ast'; -import { GaugeType, BasicVislibParams } from './types'; +import { GaugeType } from './types'; +import { GaugeVisParams } from './gauge'; -export const goalVisTypeDefinition: BaseVisTypeOptions = { +export const goalVisTypeDefinition: VisTypeDefinition = { name: 'goal', title: i18n.translate('visTypeVislib.goal.goalTitle', { defaultMessage: 'Goal' }), icon: 'visGoal', @@ -98,5 +99,5 @@ export const goalVisTypeDefinition: BaseVisTypeOptions = { }, ], }, - useCustomNoDataScreen: true, + requiresSearch: true, }; diff --git a/src/plugins/vis_type_vislib/public/heatmap.ts b/src/plugins/vis_type_vislib/public/heatmap.ts index 8f891263e354a..1b1f4c6530fef 100644 --- a/src/plugins/vis_type_vislib/public/heatmap.ts +++ b/src/plugins/vis_type_vislib/public/heatmap.ts @@ -12,12 +12,12 @@ import { Position } from '@elastic/charts'; import { RangeValues } from '../../vis_default_editor/public'; import { AggGroupNames } from '../../data/public'; import { ColorSchemas, ColorSchemaParams } from '../../charts/public'; -import { VIS_EVENT_TO_TRIGGER, BaseVisTypeOptions } from '../../visualizations/public'; +import { VIS_EVENT_TO_TRIGGER, VisTypeDefinition } from '../../visualizations/public'; import { ValueAxis, ScaleType, AxisType } from '../../vis_type_xy/public'; import { HeatmapOptions, getHeatmapCollections } from './editor'; import { TimeMarker } from './vislib/visualizations/time_marker'; -import { CommonVislibParams, BasicVislibParams, VislibChartType } from './types'; +import { CommonVislibParams, VislibChartType } from './types'; import { toExpressionAst } from './to_ast'; export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaParams { @@ -32,7 +32,7 @@ export interface HeatmapVisParams extends CommonVislibParams, ColorSchemaParams times: TimeMarker[]; } -export const heatmapVisTypeDefinition: BaseVisTypeOptions = { +export const heatmapVisTypeDefinition: VisTypeDefinition = { name: 'heatmap', title: i18n.translate('visTypeVislib.heatmap.heatmapTitle', { defaultMessage: 'Heat map' }), icon: 'heatmap', @@ -127,4 +127,5 @@ export const heatmapVisTypeDefinition: BaseVisTypeOptions = { }, ], }, + requiresSearch: true, }; diff --git a/src/plugins/vis_type_vislib/public/histogram.ts b/src/plugins/vis_type_vislib/public/histogram.ts index 8116b40e9522e..5162df2e6d985 100644 --- a/src/plugins/vis_type_vislib/public/histogram.ts +++ b/src/plugins/vis_type_vislib/public/histogram.ts @@ -7,13 +7,12 @@ */ import { xyVisTypes } from '../../vis_type_xy/public'; -import { BaseVisTypeOptions } from '../../visualizations/public'; +import { VisTypeDefinition } from '../../visualizations/public'; import { toExpressionAst } from './to_ast'; import { BasicVislibParams } from './types'; -export const histogramVisTypeDefinition: BaseVisTypeOptions = { - ...(xyVisTypes.histogram() as BaseVisTypeOptions), +export const histogramVisTypeDefinition = { + ...xyVisTypes.histogram(), toExpressionAst, - visualization: undefined, -}; +} as VisTypeDefinition; diff --git a/src/plugins/vis_type_vislib/public/horizontal_bar.ts b/src/plugins/vis_type_vislib/public/horizontal_bar.ts index b07261bc89b56..14c214a13e903 100644 --- a/src/plugins/vis_type_vislib/public/horizontal_bar.ts +++ b/src/plugins/vis_type_vislib/public/horizontal_bar.ts @@ -7,13 +7,12 @@ */ import { xyVisTypes } from '../../vis_type_xy/public'; -import { BaseVisTypeOptions } from '../../visualizations/public'; +import { VisTypeDefinition } from '../../visualizations/public'; import { toExpressionAst } from './to_ast'; import { BasicVislibParams } from './types'; -export const horizontalBarVisTypeDefinition: BaseVisTypeOptions = { - ...(xyVisTypes.horizontalBar() as BaseVisTypeOptions), +export const horizontalBarVisTypeDefinition = { + ...xyVisTypes.horizontalBar(), toExpressionAst, - visualization: undefined, -}; +} as VisTypeDefinition; diff --git a/src/plugins/vis_type_vislib/public/line.ts b/src/plugins/vis_type_vislib/public/line.ts index 80840427a016c..33f2cc2969345 100644 --- a/src/plugins/vis_type_vislib/public/line.ts +++ b/src/plugins/vis_type_vislib/public/line.ts @@ -7,13 +7,12 @@ */ import { xyVisTypes } from '../../vis_type_xy/public'; -import { BaseVisTypeOptions } from '../../visualizations/public'; +import { VisTypeDefinition } from '../../visualizations/public'; import { toExpressionAst } from './to_ast'; import { BasicVislibParams } from './types'; -export const lineVisTypeDefinition: BaseVisTypeOptions = { - ...(xyVisTypes.line() as BaseVisTypeOptions), +export const lineVisTypeDefinition = { + ...xyVisTypes.line(), toExpressionAst, - visualization: undefined, -}; +} as VisTypeDefinition; diff --git a/src/plugins/vis_type_vislib/public/pie.ts b/src/plugins/vis_type_vislib/public/pie.ts index 1311706aa2799..974be507ba113 100644 --- a/src/plugins/vis_type_vislib/public/pie.ts +++ b/src/plugins/vis_type_vislib/public/pie.ts @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { Position } from '@elastic/charts'; import { AggGroupNames } from '../../data/public'; -import { BaseVisTypeOptions, VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; +import { VisTypeDefinition, VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; import { getPositions } from '../../vis_type_xy/public'; import { CommonVislibParams } from './types'; @@ -28,7 +28,7 @@ export interface PieVisParams extends CommonVislibParams { }; } -export const pieVisTypeDefinition: BaseVisTypeOptions = { +export const pieVisTypeDefinition: VisTypeDefinition = { name: 'pie', title: i18n.translate('visTypeVislib.pie.pieTitle', { defaultMessage: 'Pie' }), icon: 'visPie', @@ -93,5 +93,5 @@ export const pieVisTypeDefinition: BaseVisTypeOptions = { ], }, hierarchicalData: true, - responseHandler: 'vislib_slices', + requiresSearch: true, }; diff --git a/src/plugins/vis_type_vislib/public/to_ast.ts b/src/plugins/vis_type_vislib/public/to_ast.ts index be51ee70e6368..bad3d731a0887 100644 --- a/src/plugins/vis_type_vislib/public/to_ast.ts +++ b/src/plugins/vis_type_vislib/public/to_ast.ts @@ -8,7 +8,12 @@ import moment from 'moment'; -import { VisToExpressionAst, getVisSchemas } from '../../visualizations/public'; +import { + Vis, + VisToExpressionAstParams, + getVisSchemas, + VisParams, +} from '../../visualizations/public'; import { buildExpression, buildExpressionFunction } from '../../expressions/public'; import type { Dimensions, DateHistogramParams, HistogramParams } from '../../vis_type_xy/public'; import { BUCKET_TYPES } from '../../data/public'; @@ -17,7 +22,10 @@ import { vislibVisName, VisTypeVislibExpressionFunctionDefinition } from './vis_ import { BasicVislibParams, VislibChartType } from './types'; import { getEsaggsFn } from './to_ast_esaggs'; -export const toExpressionAst: VisToExpressionAst = async (vis, params) => { +export const toExpressionAst = async ( + vis: Vis, + params: VisToExpressionAstParams +) => { const schemas = getVisSchemas(vis, params); const dimensions: Dimensions = { x: schemas.segment ? schemas.segment[0] : null, @@ -58,9 +66,11 @@ export const toExpressionAst: VisToExpressionAst = async (vis (dimensions.y || []).forEach((yDimension) => { const yAgg = responseAggs.filter(({ enabled }) => enabled)[yDimension.accessor]; - const seriesParam = (visConfig.seriesParams || []).find((param) => param.data.id === yAgg.id); + const seriesParam = ((visConfig.seriesParams as BasicVislibParams['seriesParams']) || []).find( + (param) => param.data.id === yAgg.id + ); if (seriesParam) { - const usedValueAxis = (visConfig.valueAxes || []).find( + const usedValueAxis = ((visConfig.valueAxes as BasicVislibParams['valueAxes']) || []).find( (valueAxis) => valueAxis.id === seriesParam.valueAxis ); if (usedValueAxis?.scale.mode === 'percentage') { @@ -72,13 +82,11 @@ export const toExpressionAst: VisToExpressionAst = async (vis } }); - visConfig.dimensions = dimensions; - const visTypeVislib = buildExpressionFunction( vislibVisName, { type: vis.type.name as Exclude, - visConfig: JSON.stringify(visConfig), + visConfig: JSON.stringify({ ...visConfig, dimensions }), } ); diff --git a/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts b/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts index 2e73eea393d65..9de486fc1ba04 100644 --- a/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts +++ b/src/plugins/vis_type_vislib/public/to_ast_esaggs.ts @@ -13,16 +13,13 @@ import { IndexPatternLoadExpressionFunctionDefinition, } from '../../data/public'; -import { PieVisParams } from './pie'; -import { BasicVislibParams } from './types'; - /** * Get esaggs expressions function * TODO: replace this with vis.data.aggs!.toExpressionAst(); * https://github.com/elastic/kibana/issues/61768 * @param vis */ -export function getEsaggsFn(vis: Vis | Vis) { +export function getEsaggsFn(vis: Vis) { return buildExpressionFunction('esaggs', { index: buildExpression([ buildExpressionFunction('indexPatternLoad', { diff --git a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts index c80ddbd8976b3..52212741fe9df 100644 --- a/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts +++ b/src/plugins/vis_type_vislib/public/vis_type_vislib_vis_types.ts @@ -6,6 +6,7 @@ * Public License, v 1. */ +import { VisTypeDefinition } from 'src/plugins/visualizations/public'; import { histogramVisTypeDefinition } from './histogram'; import { lineVisTypeDefinition } from './line'; import { areaVisTypeDefinition } from './area'; @@ -16,7 +17,7 @@ import { goalVisTypeDefinition } from './goal'; export { pieVisTypeDefinition } from './pie'; -export const visLibVisTypeDefinitions = [ +export const visLibVisTypeDefinitions: Array> = [ histogramVisTypeDefinition, lineVisTypeDefinition, areaVisTypeDefinition, @@ -26,7 +27,7 @@ export const visLibVisTypeDefinitions = [ goalVisTypeDefinition, ]; -export const convertedTypeDefinitions = [ +export const convertedTypeDefinitions: Array> = [ heatmapVisTypeDefinition, gaugeVisTypeDefinition, goalVisTypeDefinition, diff --git a/src/plugins/vis_type_xy/public/editor/collections.ts b/src/plugins/vis_type_xy/public/editor/collections.ts index e976ceebb1353..bfce92abdb7ef 100644 --- a/src/plugins/vis_type_xy/public/editor/collections.ts +++ b/src/plugins/vis_type_xy/public/editor/collections.ts @@ -143,39 +143,38 @@ export const getRotateOptions = () => [ }, ]; -export const getFittingFunctions = () => - [ - { - value: Fit.None, - text: i18n.translate('visTypeXy.fittingFunctionsTitle.none', { - defaultMessage: 'Hide (Do not fill gaps)', - }), - }, - { - value: Fit.Zero, - text: i18n.translate('visTypeXy.fittingFunctionsTitle.zero', { - defaultMessage: 'Zero (Fill gaps with zeros)', - }), - }, - { - value: Fit.Linear, - text: i18n.translate('visTypeXy.fittingFunctionsTitle.linear', { - defaultMessage: 'Linear (Fill gaps with a line)', - }), - }, - { - value: Fit.Carry, - text: i18n.translate('visTypeXy.fittingFunctionsTitle.carry', { - defaultMessage: 'Last (Fill gaps with the last value)', - }), - }, - { - value: Fit.Lookahead, - text: i18n.translate('visTypeXy.fittingFunctionsTitle.lookahead', { - defaultMessage: 'Next (Fill gaps with the next value)', - }), - }, - ] as const; +export const getFittingFunctions = () => [ + { + value: Fit.None, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.none', { + defaultMessage: 'Hide (Do not fill gaps)', + }), + }, + { + value: Fit.Zero, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.zero', { + defaultMessage: 'Zero (Fill gaps with zeros)', + }), + }, + { + value: Fit.Linear, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.linear', { + defaultMessage: 'Linear (Fill gaps with a line)', + }), + }, + { + value: Fit.Carry, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.carry', { + defaultMessage: 'Last (Fill gaps with the last value)', + }), + }, + { + value: Fit.Lookahead, + text: i18n.translate('visTypeXy.fittingFunctionsTitle.lookahead', { + defaultMessage: 'Next (Fill gaps with the next value)', + }), + }, +]; export const getConfigCollections = () => ({ legendPositions: getPositions(), diff --git a/src/plugins/vis_type_xy/public/editor/common_config.tsx b/src/plugins/vis_type_xy/public/editor/common_config.tsx index 4cfb18b4a0b11..1d635463cd963 100644 --- a/src/plugins/vis_type_xy/public/editor/common_config.tsx +++ b/src/plugins/vis_type_xy/public/editor/common_config.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { VisOptionsProps } from '../../../vis_default_editor/public'; +import { VisEditorOptionsProps } from '../../../visualizations/public'; import { VisParams } from '../types'; import { MetricsAxisOptions, PointSeriesOptions } from './components/options'; @@ -22,7 +22,7 @@ export function getOptionTabs(showElasticChartsOptions = false) { title: i18n.translate('visTypeXy.area.tabs.metricsAxesTitle', { defaultMessage: 'Metrics & axes', }), - editor: (props: VisOptionsProps) => ( + editor: (props: VisEditorOptionsProps) => ( ), }, @@ -31,7 +31,7 @@ export function getOptionTabs(showElasticChartsOptions = false) { title: i18n.translate('visTypeXy.area.tabs.panelSettingsTitle', { defaultMessage: 'Panel settings', }), - editor: (props: VisOptionsProps) => ( + editor: (props: VisEditorOptionsProps) => ( extends VisOptionsProps { +export interface ValidationVisOptionsProps extends VisEditorOptionsProps { setMultipleValidity(paramName: string, isValid: boolean): void; extraProps?: E; } -interface ValidationWrapperProps extends VisOptionsProps { +interface ValidationWrapperProps extends VisEditorOptionsProps { component: React.ComponentType>; extraProps?: E; } diff --git a/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx index edb6cfac3c2dd..f863d668985d8 100644 --- a/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx +++ b/src/plugins/vis_type_xy/public/editor/components/options/metrics_axes/category_axis_panel.tsx @@ -13,11 +13,8 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiPanel, EuiTitle, EuiSpacer } from '@elastic/eui'; import { Position } from '@elastic/charts'; -import { - SelectOption, - SwitchOption, - VisOptionsProps, -} from '../../../../../../vis_default_editor/public'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; +import { SelectOption, SwitchOption } from '../../../../../../vis_default_editor/public'; import { LabelOptions, SetAxisLabel } from './label_options'; import { CategoryAxis } from '../../../../types'; @@ -26,7 +23,7 @@ export interface CategoryAxisPanelProps { axis: CategoryAxis; onPositionChanged: (position: Position) => void; setCategoryAxis: (value: CategoryAxis) => void; - vis: VisOptionsProps['vis']; + vis: VisEditorOptionsProps['vis']; } function CategoryAxisPanel({ diff --git a/src/plugins/vis_type_xy/public/sample_vis.test.mocks.ts b/src/plugins/vis_type_xy/public/sample_vis.test.mocks.ts index 324ea96c082ba..880161293ca25 100644 --- a/src/plugins/vis_type_xy/public/sample_vis.test.mocks.ts +++ b/src/plugins/vis_type_xy/public/sample_vis.test.mocks.ts @@ -106,10 +106,7 @@ export const samplePieVis = { }, }, hidden: false, - requestHandler: 'courier', - responseHandler: 'vislib_slices', hierarchicalData: true, - useCustomNoDataScreen: false, }, title: '[Flights] Airline Carrier', description: '', @@ -126,7 +123,6 @@ export const samplePieVis = { truncate: 100, }, }, - sessionState: {}, data: { searchSource: { id: 'data_source1', @@ -1622,10 +1618,7 @@ export const sampleAreaVis = { }, }, hidden: false, - requestHandler: 'courier', - responseHandler: 'none', hierarchicalData: false, - useCustomNoDataScreen: false, }, title: '[eCommerce] Sales by Category', description: '', @@ -1762,7 +1755,6 @@ export const sampleAreaVis = { ], }, }, - sessionState: {}, data: { searchSource: { id: 'data_source1', diff --git a/src/plugins/vis_type_xy/public/types/vis_type.ts b/src/plugins/vis_type_xy/public/types/vis_type.ts index 3decb8854d355..19b8b88ec5f66 100644 --- a/src/plugins/vis_type_xy/public/types/vis_type.ts +++ b/src/plugins/vis_type_xy/public/types/vis_type.ts @@ -6,16 +6,11 @@ * Public License, v 1. */ -import { BaseVisTypeOptions } from '../../../visualizations/public'; +import { VisTypeDefinition } from '../../../visualizations/public'; import { ChartType } from '../../common'; import { VisParams } from './param'; export type VisTypeNames = ChartType | 'horizontal_bar'; -export type XyVisTypeDefinition = BaseVisTypeOptions & { - name: VisTypeNames; - visConfig: { - defaults: Omit; - }; -}; +export type XyVisTypeDefinition = VisTypeDefinition; diff --git a/src/plugins/vis_type_xy/public/vis_types/area.ts b/src/plugins/vis_type_xy/public/vis_types/area.ts index 09007a01ca8bc..24045a5c308b4 100644 --- a/src/plugins/vis_type_xy/public/vis_types/area.ts +++ b/src/plugins/vis_type_xy/public/vis_types/area.ts @@ -181,4 +181,5 @@ export const getAreaVisTypeDefinition = ( }, ], }, + requiresSearch: true, }); diff --git a/src/plugins/vis_type_xy/public/vis_types/histogram.ts b/src/plugins/vis_type_xy/public/vis_types/histogram.ts index daae5f5e48e61..c5a2825e7420b 100644 --- a/src/plugins/vis_type_xy/public/vis_types/histogram.ts +++ b/src/plugins/vis_type_xy/public/vis_types/histogram.ts @@ -184,4 +184,5 @@ export const getHistogramVisTypeDefinition = ( }, ], }, + requiresSearch: true, }); diff --git a/src/plugins/vis_type_xy/public/vis_types/horizontal_bar.ts b/src/plugins/vis_type_xy/public/vis_types/horizontal_bar.ts index 9e026fa0d7474..b6821b268f5c5 100644 --- a/src/plugins/vis_type_xy/public/vis_types/horizontal_bar.ts +++ b/src/plugins/vis_type_xy/public/vis_types/horizontal_bar.ts @@ -183,4 +183,5 @@ export const getHorizontalBarVisTypeDefinition = ( }, ], }, + requiresSearch: true, }); diff --git a/src/plugins/vis_type_xy/public/vis_types/line.ts b/src/plugins/vis_type_xy/public/vis_types/line.ts index 3f3087207fa19..093b7efb6af36 100644 --- a/src/plugins/vis_type_xy/public/vis_types/line.ts +++ b/src/plugins/vis_type_xy/public/vis_types/line.ts @@ -175,4 +175,5 @@ export const getLineVisTypeDefinition = ( }, ], }, + requiresSearch: true, }); diff --git a/src/plugins/visualizations/public/components/__snapshots__/visualization_requesterror.test.js.snap b/src/plugins/visualizations/public/components/__snapshots__/visualization_requesterror.test.js.snap deleted file mode 100644 index d1dde7340cfa1..0000000000000 --- a/src/plugins/visualizations/public/components/__snapshots__/visualization_requesterror.test.js.snap +++ /dev/null @@ -1,24 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`VisualizationRequestError should render according to snapshot 1`] = ` -

-
-
- -
- Request error -
-
-
-`; diff --git a/src/plugins/visualizations/public/components/_visualization.scss b/src/plugins/visualizations/public/components/_visualization.scss index e8d4c5c6db445..42b59b8de93cd 100644 --- a/src/plugins/visualizations/public/components/_visualization.scss +++ b/src/plugins/visualizations/public/components/_visualization.scss @@ -15,48 +15,6 @@ position: relative; padding: $euiSizeS; flex: 1 1 100%; - - /** - * 1. Expand to fill the container but accept being squeezed smaller by the spy, even so small - * that it disappears entirely. - */ - .visChart__container { - @include euiScrollBar; - min-height: 0; - flex: 1 1 0; /* 1 */ - display: flex; - flex-direction: row; - overflow: auto; - transition: opacity .01s; - - // IE11 Hack - // - // Normally we would just set flex: 1 1 0%, which works as expected in IE11. - // Unfortunately, a recent bug in Firefox causes this rule to be ignored, so we - // have to use an IE-specific hack instead. - @include internetExplorerOnly() { - flex: 1 0; - } - - &:focus { - box-shadow: none; - } - } - - // SASSTODO: Can't find exact usage - .loading { - opacity: .5; - } - - // SASSTODO: Can't find exact usage - .spinner { - position: absolute; - top: 40%; - left: 0; - right: 0; - z-index: 20; - opacity: .5; - } } .visChart { diff --git a/src/plugins/visualizations/public/components/index.ts b/src/plugins/visualizations/public/components/index.ts index 88f3acf20d39b..1d6b6b5d911ea 100644 --- a/src/plugins/visualizations/public/components/index.ts +++ b/src/plugins/visualizations/public/components/index.ts @@ -6,6 +6,4 @@ * Public License, v 1. */ -export { Visualization } from './visualization'; export { VisualizationContainer } from './visualization_container'; -export { VisualizationNoResults } from './visualization_noresults'; diff --git a/src/plugins/visualizations/public/components/visualization.test.js b/src/plugins/visualizations/public/components/visualization.test.js deleted file mode 100644 index cb332232cbc55..0000000000000 --- a/src/plugins/visualizations/public/components/visualization.test.js +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -jest.useFakeTimers(); - -import React from 'react'; -import { render, mount } from 'enzyme'; -import { Visualization } from './visualization'; - -let renderPromise; -class VisualizationStub { - constructor(el, vis) { - this.el = el; - this.vis = vis; - } - - render() { - renderPromise = new Promise((resolve) => { - this.el.innerText = this.vis.params.markdown; - resolve(); - }); - - return renderPromise; - } -} - -describe('', () => { - const visData = { - hits: 1, - }; - - const uiState = { - on: () => {}, - off: () => {}, - set: () => {}, - }; - - let vis; - - beforeEach(() => { - vis = { - setUiState: function (uiState) { - this.uiState = uiState; - }, - getUiState: function () { - return this.uiState; - }, - params: {}, - type: { - title: 'new vis', - requiresSearch: true, - useCustomNoDataScreen: false, - visualization: VisualizationStub, - }, - }; - }); - - it('should display no result message when length of data is 0', () => { - const data = { rows: [] }; - const wrapper = render( - - ); - expect(wrapper.text()).toBe('No results found'); - }); - - it('should render chart when data is present', () => { - const wrapper = render( - - ); - expect(wrapper.text()).not.toBe('No results found'); - }); - - it('should call onInit when rendering no data', () => { - const spy = jest.fn(); - const noData = { hits: 0 }; - mount( - - ); - expect(spy).toHaveBeenCalled(); - }); -}); diff --git a/src/plugins/visualizations/public/components/visualization.tsx b/src/plugins/visualizations/public/components/visualization.tsx deleted file mode 100644 index bdabe6bc07297..0000000000000 --- a/src/plugins/visualizations/public/components/visualization.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { get } from 'lodash'; -import React from 'react'; -import { PersistedState } from '../../../../plugins/visualizations/public'; -import { memoizeLast } from '../legacy/memoize'; -import { VisualizationChart } from './visualization_chart'; -import { VisualizationNoResults } from './visualization_noresults'; -import { ExprVis } from '../expressions/vis'; - -function shouldShowNoResultsMessage(vis: ExprVis, visData: any): boolean { - const requiresSearch = get(vis, 'type.requiresSearch'); - const rows: object[] | undefined = get(visData, 'rows'); - const isZeroHits = get(visData, 'hits') === 0 || (rows && !rows.length); - const shouldShowMessage = !get(vis, 'type.useCustomNoDataScreen'); - - return Boolean(requiresSearch && isZeroHits && shouldShowMessage); -} - -interface VisualizationProps { - listenOnChange: boolean; - onInit?: () => void; - uiState: PersistedState; - vis: ExprVis; - visData: any; - visParams: any; -} - -export class Visualization extends React.Component { - private showNoResultsMessage = memoizeLast(shouldShowNoResultsMessage); - - constructor(props: VisualizationProps) { - super(props); - - props.vis.setUiState(props.uiState); - } - - public render() { - const { vis, visData, visParams, onInit, uiState, listenOnChange } = this.props; - - const noResults = this.showNoResultsMessage(vis, visData); - - return ( -
- {noResults ? ( - - ) : ( - - )} -
- ); - } - - public shouldComponentUpdate(nextProps: VisualizationProps): boolean { - if (nextProps.uiState !== this.props.uiState) { - throw new Error('Changing uiState on is not supported!'); - } - return true; - } -} diff --git a/src/plugins/visualizations/public/components/visualization_chart.test.js b/src/plugins/visualizations/public/components/visualization_chart.test.js deleted file mode 100644 index 98cc5bb8d0729..0000000000000 --- a/src/plugins/visualizations/public/components/visualization_chart.test.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -jest.useFakeTimers(); - -import React from 'react'; -import { render, mount } from 'enzyme'; -import { VisualizationChart } from './visualization_chart'; - -let renderPromise; - -class VisualizationStub { - constructor(el, vis) { - this.el = el; - this.vis = vis; - } - - render() { - renderPromise = new Promise((resolve) => { - this.el.textContent = this.vis.params.markdown; - resolve(); - }); - - return renderPromise; - } -} - -describe('', () => { - const vis = { - type: { - title: 'Test Visualization', - visualization: VisualizationStub, - }, - params: { - markdown: - 'This is a test of the [markdown](http://daringfireball.net/projects/markdown) vis.', - }, - }; - - it('should render initial html', () => { - const wrapper = render(); - expect(wrapper.text()).toBe(''); - }); - - it('should render visualization', async () => { - const wrapper = mount(); - jest.runAllTimers(); - await renderPromise; - expect(wrapper.find('.visChart').text()).toMatch(/markdown/); - }); -}); diff --git a/src/plugins/visualizations/public/components/visualization_chart.tsx b/src/plugins/visualizations/public/components/visualization_chart.tsx deleted file mode 100644 index c6ad1c53f91b7..0000000000000 --- a/src/plugins/visualizations/public/components/visualization_chart.tsx +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import React from 'react'; -import * as Rx from 'rxjs'; -import { debounceTime, filter, share, switchMap } from 'rxjs/operators'; -import { PersistedState } from '../../../../plugins/visualizations/public'; -import { VisualizationController } from '../types'; -import { ResizeChecker } from '../../../../plugins/kibana_utils/public'; -import { ExprVis } from '../expressions/vis'; - -interface VisualizationChartProps { - onInit?: () => void; - uiState: PersistedState; - vis: ExprVis; - visData: any; - visParams: any; - listenOnChange: boolean; -} - -class VisualizationChart extends React.Component { - private resizeChecker?: ResizeChecker; - private visualization?: VisualizationController; - private chartDiv = React.createRef(); - private containerDiv = React.createRef(); - private renderSubject: Rx.Subject<{ - vis: ExprVis; - visParams: any; - visData: any; - }>; - private renderSubscription: Rx.Subscription; - - constructor(props: VisualizationChartProps) { - super(props); - - this.renderSubject = new Rx.Subject(); - const render$ = this.renderSubject.asObservable().pipe(share()); - - const success$ = render$.pipe( - filter(({ vis, visData }) => vis && (!vis.type.requiresSearch || visData)), - debounceTime(100), - switchMap(async ({ vis, visData, visParams }) => { - if (!this.visualization) { - // This should never happen, since we only should trigger another rendering - // after this component has mounted and thus the visualization implementation - // has been initialized - throw new Error('Visualization implementation was not initialized on first render.'); - } - - return this.visualization.render(visData, visParams); - }) - ); - - this.renderSubscription = success$.subscribe(() => { - if (this.props.onInit) { - this.props.onInit(); - } - }); - } - - public render() { - return ( -
-
-
- ); - } - - public componentDidMount() { - if (!this.chartDiv.current || !this.containerDiv.current) { - throw new Error('chartDiv and currentDiv reference should always be present.'); - } - - const { vis } = this.props; - const Visualization = vis.type.visualization; - - if (!Visualization) { - throw new Error( - 'Tried to use VisualizationChart component with a vis without visualization property.' - ); - } - - this.visualization = new Visualization(this.chartDiv.current, vis); - - // We know that containerDiv.current will never be null, since we will always - // have rendered and the div is always rendered into the tree (i.e. not - // inside any condition). - this.resizeChecker = new ResizeChecker(this.containerDiv.current); - this.resizeChecker.on('resize', () => this.startRenderVisualization()); - - if (this.props.listenOnChange) { - this.props.uiState.on('change', this.onUiStateChanged); - } - - this.startRenderVisualization(); - } - - public componentDidUpdate() { - this.startRenderVisualization(); - } - - public componentWillUnmount() { - if (this.renderSubscription) { - this.renderSubscription.unsubscribe(); - } - if (this.resizeChecker) { - this.resizeChecker.destroy(); - } - if (this.visualization) { - this.visualization.destroy(); - } - } - - private onUiStateChanged = () => { - this.startRenderVisualization(); - }; - - private startRenderVisualization(): void { - if (this.containerDiv.current && this.chartDiv.current) { - this.renderSubject.next({ - vis: this.props.vis, - visData: this.props.visData, - visParams: this.props.visParams, - }); - } - } -} - -export { VisualizationChart }; diff --git a/src/plugins/visualizations/public/components/visualization_requesterror.test.js b/src/plugins/visualizations/public/components/visualization_requesterror.test.js deleted file mode 100644 index 8a183efe3faa6..0000000000000 --- a/src/plugins/visualizations/public/components/visualization_requesterror.test.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import React from 'react'; -import { render } from 'enzyme'; -import { VisualizationRequestError } from './visualization_requesterror'; - -describe('VisualizationRequestError', () => { - it('should render according to snapshot', () => { - const wrapper = render(); - expect(wrapper).toMatchSnapshot(); - }); - - it('should set html when error is an object', () => { - const wrapper = render(); - expect(wrapper.text()).toBe('Request error'); - }); - - it('should set html when error is a string', () => { - const wrapper = render(); - expect(wrapper.text()).toBe('Request error'); - }); -}); diff --git a/src/plugins/visualizations/public/components/visualization_requesterror.tsx b/src/plugins/visualizations/public/components/visualization_requesterror.tsx deleted file mode 100644 index 3378875327959..0000000000000 --- a/src/plugins/visualizations/public/components/visualization_requesterror.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; -import React from 'react'; -import { SearchError } from '../../../../plugins/data/public'; - -interface VisualizationRequestErrorProps { - onInit?: () => void; - error: SearchError | string; -} - -export class VisualizationRequestError extends React.Component { - private containerDiv = React.createRef(); - - public render() { - const { error } = this.props; - const errorMessage = typeof error === 'string' ? error : error.message; - - return ( -
- - - - - - {errorMessage} - -
- ); - } - - public componentDidMount() { - this.afterRender(); - } - - public componentDidUpdate() { - this.afterRender(); - } - - private afterRender() { - if (this.props.onInit) { - this.props.onInit(); - } - } -} diff --git a/src/plugins/visualizations/public/embeddable/_embeddables.scss b/src/plugins/visualizations/public/embeddable/_embeddables.scss index f0ec8479489d2..2a4d5c14a46a5 100644 --- a/src/plugins/visualizations/public/embeddable/_embeddables.scss +++ b/src/plugins/visualizations/public/embeddable/_embeddables.scss @@ -8,10 +8,6 @@ @include euiScrollBar; /* 2 */ } - .visualization .visChart__container { - overflow: visible; /* 1 */ - } - .visLegend__toggle { border-bottom-right-radius: 0; border-top-left-radius: 0; diff --git a/src/plugins/visualizations/public/embeddable/get_index_pattern.ts b/src/plugins/visualizations/public/embeddable/get_index_pattern.ts deleted file mode 100644 index 65c6ebe75daf5..0000000000000 --- a/src/plugins/visualizations/public/embeddable/get_index_pattern.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { VisSavedObject } from '../types'; -import type { IndexPattern } from '../../../../plugins/data/public'; -import { getIndexPatterns } from '../services'; - -export async function getIndexPattern( - savedVis: VisSavedObject -): Promise { - if (savedVis.visState.type !== 'metrics') { - return savedVis.searchSource!.getField('index'); - } - - const indexPatternsClient = getIndexPatterns(); - - return savedVis.visState.params.index_pattern - ? (await indexPatternsClient.find(`"${savedVis.visState.params.index_pattern}"`))[0] - : await indexPatternsClient.getDefault(); -} diff --git a/src/plugins/visualizations/public/embeddable/to_ast.ts b/src/plugins/visualizations/public/embeddable/to_ast.ts new file mode 100644 index 0000000000000..31a9db5b92d11 --- /dev/null +++ b/src/plugins/visualizations/public/embeddable/to_ast.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { ExpressionFunctionKibana, ExpressionFunctionKibanaContext } from '../../../data/public'; +import { buildExpression, buildExpressionFunction } from '../../../expressions/public'; + +import { VisToExpressionAst } from '../types'; + +/** + * Creates an ast expression for a visualization based on kibana context (query, filters, timerange) + * including a saved search if the visualization is based on it. + * The expression also includes particular visualization expression ast if presented. + * + * @internal + */ +export const toExpressionAst: VisToExpressionAst = async (vis, params) => { + const { savedSearchId, searchSource } = vis.data; + const query = searchSource?.getField('query'); + const filters = searchSource?.getField('filter'); + + const kibana = buildExpressionFunction('kibana', {}); + const kibanaContext = buildExpressionFunction('kibana_context', { + q: query && JSON.stringify(query), + filters: filters && JSON.stringify(filters), + savedSearchId, + }); + + const ast = buildExpression([kibana, kibanaContext]); + const expression = ast.toAst(); + + if (!vis.type.toExpressionAst) { + throw new Error('Visualization type definition should have toExpressionAst function defined'); + } + + const visExpressionAst = await vis.type.toExpressionAst(vis, params); + // expand the expression chain with a particular visualization expression chain, if it exists + expression.chain.push(...visExpressionAst.chain); + + return expression; +}; diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index 88fc6e6a98c0d..45bd6a8a9d554 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -32,8 +32,8 @@ import { IExpressionLoaderParams, ExpressionsStart, ExpressionRenderError, + ExpressionAstExpression, } from '../../../../plugins/expressions/public'; -import { buildPipeline } from '../legacy/build_pipeline'; import { Vis, SerializedVis } from '../vis'; import { getExpressions, getUiActions } from '../services'; import { VIS_EVENT_TO_TRIGGER } from './events'; @@ -41,6 +41,7 @@ import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory'; import { SavedObjectAttributes } from '../../../../core/types'; import { SavedVisualizationsLoader } from '../saved_visualizations'; import { VisSavedObject } from '../types'; +import { toExpressionAst } from './to_ast'; const getKeys = (o: T): Array => Object.keys(o) as Array; @@ -94,7 +95,7 @@ export class VisualizeEmbeddable private syncColors?: boolean; private visCustomizations?: Pick; private subscriptions: Subscription[] = []; - private expression: string = ''; + private expression?: ExpressionAstExpression; private vis: Vis; private domNode: any; public readonly type = VISUALIZE_EMBEDDABLE_TYPE; @@ -382,7 +383,7 @@ export class VisualizeEmbeddable } this.abortController = new AbortController(); const abortController = this.abortController; - this.expression = await buildPipeline(this.vis, { + this.expression = await toExpressionAst(this.vis, { timefilter: this.timefilter, timeRange: this.timeRange, abortSignal: this.abortController!.signal, diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx index 399e0e4b71532..6a57bf7b4477a 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx @@ -74,12 +74,12 @@ export class VisualizeEmbeddableFactory type: 'visualization', getIconForSavedObject: (savedObject) => { return ( - getTypes().get(JSON.parse(savedObject.attributes.visState).type).icon || 'visualizeApp' + getTypes().get(JSON.parse(savedObject.attributes.visState).type)?.icon || 'visualizeApp' ); }, getTooltipForSavedObject: (savedObject) => { return `${savedObject.attributes.title} (${ - getTypes().get(JSON.parse(savedObject.attributes.visState).type).title + getTypes().get(JSON.parse(savedObject.attributes.visState).type)?.title })`; }, showSavedObject: (savedObject) => { diff --git a/src/plugins/visualizations/public/expressions/vis.ts b/src/plugins/visualizations/public/expressions/vis.ts deleted file mode 100644 index a3952d284805d..0000000000000 --- a/src/plugins/visualizations/public/expressions/vis.ts +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -/** - * @name Vis - * - * @description This class consists of aggs, params, listeners, title, and type. - * - Aggs: Instances of AggConfig. - * - Params: The settings in the Options tab. - * - * Not to be confused with vislib/vis.js. - */ - -import { EventEmitter } from 'events'; -import _ from 'lodash'; -import { VisParams, PersistedState } from '../../../../plugins/visualizations/public'; - -import { getTypes } from '../services'; -import { VisType } from '../vis_types'; - -export interface ExprVisState { - title?: string; - type: VisType | string; - params?: VisParams; -} - -export interface ExprVisAPIEvents { - filter: (data: any) => void; - brush: (data: any) => void; - applyFilter: (data: any) => void; -} - -export interface ExprVisAPI { - events: ExprVisAPIEvents; -} - -export class ExprVis extends EventEmitter { - public title: string = ''; - public type: VisType; - public params: VisParams = {}; - public sessionState: Record = {}; - public API: ExprVisAPI; - public eventsSubject: any; - private uiState: PersistedState; - - constructor(visState: ExprVisState = { type: 'histogram' }) { - super(); - - this.type = this.getType(visState.type); - this.uiState = new PersistedState(); - this.setState(visState); - - this.API = { - events: { - filter: (data: any) => { - if (!this.eventsSubject) return; - this.eventsSubject.next({ - name: 'filterBucket', - data: data.data - ? { - data: data.data, - negate: data.negate, - } - : { data: [data] }, - }); - }, - brush: (data: any) => { - if (!this.eventsSubject) return; - this.eventsSubject.next({ name: 'brush', data }); - }, - applyFilter: (data: any) => { - if (!this.eventsSubject) return; - this.eventsSubject.next({ name: 'applyFilter', data }); - }, - }, - }; - } - - private getType(type: string | VisType) { - if (_.isString(type)) { - const newType = getTypes().get(type); - if (!newType) { - throw new Error(`Invalid type "${type}"`); - } - return newType; - } else { - return type; - } - } - - setState(state: ExprVisState) { - this.title = state.title || ''; - if (state.type) { - this.type = this.getType(state.type); - } - this.params = _.defaultsDeep( - {}, - _.cloneDeep(state.params || {}), - _.cloneDeep(this.type.visConfig.defaults || {}) - ); - } - - getState() { - return { - title: this.title, - type: this.type.name, - params: _.cloneDeep(this.params), - }; - } - - updateState() { - this.emit('update'); - } - - forceReload() { - this.emit('reload'); - } - - isHierarchical() { - if (_.isFunction(this.type.hierarchicalData)) { - return !!this.type.hierarchicalData(this); - } else { - return !!this.type.hierarchicalData; - } - } - - hasUiState() { - return !!this.uiState; - } - - getUiState() { - return this.uiState; - } - - setUiState(state: PersistedState) { - this.uiState = state; - } - - /** - * Currently this is only used to extract map-specific information - * (e.g. mapZoom, mapCenter). - */ - uiStateVal(key: string, val: any) { - if (this.hasUiState()) { - if (_.isUndefined(val)) { - return this.uiState.get(key); - } - return this.uiState.set(key, val); - } - return val; - } -} diff --git a/src/plugins/visualizations/public/expressions/visualization_function.ts b/src/plugins/visualizations/public/expressions/visualization_function.ts deleted file mode 100644 index 623fb303baccc..0000000000000 --- a/src/plugins/visualizations/public/expressions/visualization_function.ts +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { get } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { VisResponseValue, PersistedState } from '../../../../plugins/visualizations/public'; -import { ExpressionFunctionDefinition, Render } from '../../../../plugins/expressions/public'; -import { getTypes, getIndexPatterns, getFilterManager, getSearch } from '../services'; - -interface Arguments { - index?: string | null; - metricsAtAllLevels?: boolean; - partialRows?: boolean; - type?: string; - schemas?: string; - visConfig?: string; - uiState?: string; - aggConfigs?: string; -} - -export type ExpressionFunctionVisualization = ExpressionFunctionDefinition< - 'visualization', - any, - Arguments, - Promise> ->; - -export const visualization = (): ExpressionFunctionVisualization => ({ - name: 'visualization', - type: 'render', - help: i18n.translate('visualizations.functions.visualization.help', { - defaultMessage: 'A simple visualization', - }), - args: { - // TODO: Below `help` keys should be internationalized once this function - // TODO: is moved to visualizations plugin. - index: { - types: ['string', 'null'], - default: null, - help: 'Index', - }, - metricsAtAllLevels: { - types: ['boolean'], - default: false, - help: 'Metrics levels', - }, - partialRows: { - types: ['boolean'], - default: false, - help: 'Partial rows', - }, - type: { - types: ['string'], - default: '', - help: 'Type', - }, - schemas: { - types: ['string'], - default: '"{}"', - help: 'Schemas', - }, - visConfig: { - types: ['string'], - default: '"{}"', - help: 'Visualization configuration', - }, - uiState: { - types: ['string'], - default: '"{}"', - help: 'User interface state', - }, - aggConfigs: { - types: ['string'], - default: '"{}"', - help: 'Aggregation configurations', - }, - }, - async fn(input, args, { inspectorAdapters }) { - const visConfigParams = args.visConfig ? JSON.parse(args.visConfig) : {}; - const schemas = args.schemas ? JSON.parse(args.schemas) : {}; - const visType = getTypes().get(args.type || 'histogram') as any; - const indexPattern = args.index ? await getIndexPatterns().get(args.index) : null; - - const uiStateParams = args.uiState ? JSON.parse(args.uiState) : {}; - const uiState = new PersistedState(uiStateParams); - - const aggConfigsState = args.aggConfigs ? JSON.parse(args.aggConfigs) : []; - const aggs = indexPattern - ? getSearch().aggs.createAggConfigs(indexPattern, aggConfigsState) - : undefined; - - if (typeof visType.requestHandler === 'function') { - input = await visType.requestHandler({ - partialRows: args.partialRows, - metricsAtAllLevels: args.metricsAtAllLevels, - index: indexPattern, - visParams: visConfigParams, - timeRange: get(input, 'timeRange', null), - query: get(input, 'query', null), - filters: get(input, 'filters', null), - uiState, - inspectorAdapters, - queryFilter: getFilterManager(), - aggs, - }); - } - - if (typeof visType.responseHandler === 'function') { - if (input.columns) { - // assign schemas to aggConfigs - input.columns.forEach((column: any) => { - if (column.aggConfig) { - column.aggConfig.aggConfigs.schemas = visType.schemas.all; - } - }); - - Object.keys(schemas).forEach((key) => { - schemas[key].forEach((i: any) => { - if (input.columns[i] && input.columns[i].aggConfig) { - input.columns[i].aggConfig.schema = key; - } - }); - }); - } - - input = await visType.responseHandler(input, visConfigParams.dimensions); - } - - return { - type: 'render', - as: 'visualization', - value: { - visData: input, - visType: args.type || '', - visConfig: visConfigParams, - }, - }; - }, -}); diff --git a/src/plugins/visualizations/public/expressions/visualization_renderer.tsx b/src/plugins/visualizations/public/expressions/visualization_renderer.tsx deleted file mode 100644 index 3547a5d7e20ce..0000000000000 --- a/src/plugins/visualizations/public/expressions/visualization_renderer.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -// @ts-ignore -import { ExprVis } from './vis'; -import { Visualization } from '../components'; -import { VisParams } from '../types'; - -export const visualization = () => ({ - name: 'visualization', - displayName: 'visualization', - reuseDomNode: true, - render: async (domNode: HTMLElement, config: any, handlers: any) => { - const { visData, visConfig, params } = config; - const visType = config.visType || visConfig.type; - - const vis = new ExprVis({ - title: config.title, - type: visType as string, - params: visConfig as VisParams, - }); - - vis.eventsSubject = { next: handlers.event }; - - const uiState = handlers.uiState || vis.getUiState(); - - handlers.onDestroy(() => { - unmountComponentAtNode(domNode); - }); - - const listenOnChange = params ? params.listenOnChange : false; - render( - , - domNode - ); - }, -}); diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index 0bf8aa6e5c418..b4216e1fc16af 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -10,7 +10,6 @@ import { PublicContract } from '@kbn/utility-types'; import { PluginInitializerContext } from 'src/core/public'; import { VisualizationsPlugin, VisualizationsSetup, VisualizationsStart } from './plugin'; import { VisualizeEmbeddableFactory, VisualizeEmbeddable } from './embeddable'; -import { ExprVis as ExprVisClass } from './expressions/vis'; export function plugin(initializerContext: PluginInitializerContext) { return new VisualizationsPlugin(initializerContext); @@ -20,39 +19,27 @@ export function plugin(initializerContext: PluginInitializerContext) { export { Vis } from './vis'; export { TypesService } from './vis_types/types_service'; export { VISUALIZE_EMBEDDABLE_TYPE, VIS_EVENT_TO_TRIGGER } from './embeddable'; -export { VisualizationContainer, VisualizationNoResults } from './components'; -export { getSchemas as getVisSchemas } from './legacy/build_pipeline'; +export { VisualizationContainer } from './components'; +export { getVisSchemas } from './vis_schemas'; /** @public types */ export { VisualizationsSetup, VisualizationsStart }; export { VisGroups } from './vis_types'; -export type { - VisTypeAlias, - VisType, - BaseVisTypeOptions, - ReactVisTypeOptions, - Schema, - ISchemas, -} from './vis_types'; +export type { VisTypeAlias, VisTypeDefinition, Schema, ISchemas } from './vis_types'; export { SerializedVis, SerializedVisData, VisData } from './vis'; export type VisualizeEmbeddableFactoryContract = PublicContract; export type VisualizeEmbeddableContract = PublicContract; export { VisualizeInput } from './embeddable'; -export type ExprVis = ExprVisClass; -export { SchemaConfig, BuildPipelineParams } from './legacy/build_pipeline'; -// @ts-ignore +export { SchemaConfig } from './vis_schemas'; export { updateOldState } from './legacy/vis_update_state'; export { PersistedState } from './persisted_state'; export { - VisualizationControllerConstructor, - VisualizationController, ISavedVis, VisSavedObject, - VisResponseValue, VisToExpressionAst, - VisParams, + VisToExpressionAstParams, + VisEditorOptionsProps, } from './types'; -export { ExprVisAPIEvents } from './expressions/vis'; export { VisualizationListItem, VisualizationStage } from './vis_types/vis_type_alias_registry'; export { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants'; -export { SavedVisState } from '../common'; +export { SavedVisState, VisParams } from '../common'; diff --git a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap deleted file mode 100644 index 3d685064111dc..0000000000000 --- a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap +++ /dev/null @@ -1,3 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`visualize loader pipeline helpers: build pipeline buildPipeline calls toExpression on vis_type if it exists 1`] = `"kibana | kibana_context | test"`; diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts deleted file mode 100644 index a3d867380602d..0000000000000 --- a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { prepareJson, prepareString, buildPipeline } from './build_pipeline'; -import { Vis } from '..'; -import { dataPluginMock } from '../../../../plugins/data/public/mocks'; -import { parseExpression } from '../../../expressions/common'; - -describe('visualize loader pipeline helpers: build pipeline', () => { - describe('prepareJson', () => { - it('returns a correctly formatted key/value string', () => { - const expected = `foo='{}' `; // trailing space is expected - const actual = prepareJson('foo', {}); - expect(actual).toBe(expected); - }); - - it('stringifies provided data', () => { - const expected = `foo='{\"well\":\"hello\",\"there\":{\"friend\":true}}' `; - const actual = prepareJson('foo', { well: 'hello', there: { friend: true } }); - expect(actual).toBe(expected); - }); - - it('escapes single quotes', () => { - const expected = `foo='{\"well\":\"hello \\'hi\\'\",\"there\":{\"friend\":true}}' `; - const actual = prepareJson('foo', { well: `hello 'hi'`, there: { friend: true } }); - expect(actual).toBe(expected); - }); - - it('returns empty string if data is undefined', () => { - const actual = prepareJson('foo', undefined); - expect(actual).toBe(''); - }); - }); - - describe('prepareString', () => { - it('returns a correctly formatted key/value string', () => { - const expected = `foo='bar' `; // trailing space is expected - const actual = prepareString('foo', 'bar'); - expect(actual).toBe(expected); - }); - - it('escapes single quotes', () => { - const expected = `foo='\\'bar\\'' `; - const actual = prepareString('foo', `'bar'`); - expect(actual).toBe(expected); - }); - - it('returns empty string if data is undefined', () => { - const actual = prepareString('foo', undefined); - expect(actual).toBe(''); - }); - }); - - describe('buildPipeline', () => { - const dataStart = dataPluginMock.createStartContract(); - - it('calls toExpression on vis_type if it exists', async () => { - const vis = ({ - getState: () => {}, - isHierarchical: () => false, - data: { - aggs: { - getResponseAggs: () => [], - }, - searchSource: { - getField: jest.fn(), - getParent: jest.fn(), - }, - }, - // @ts-ignore - type: { - toExpressionAst: () => parseExpression('test'), - }, - } as unknown) as Vis; - const expression = await buildPipeline(vis, { - timefilter: dataStart.query.timefilter.timefilter, - }); - expect(expression).toMatchSnapshot(); - }); - }); -}); diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.ts b/src/plugins/visualizations/public/legacy/build_pipeline.ts deleted file mode 100644 index d337ef7bcf379..0000000000000 --- a/src/plugins/visualizations/public/legacy/build_pipeline.ts +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { - buildExpression, - formatExpression, - SerializedFieldFormat, -} from '../../../../plugins/expressions/public'; -import { IAggConfig, search, TimefilterContract } from '../../../../plugins/data/public'; -import { Vis } from '../types'; -const { isDateHistogramBucketAggConfig } = search.aggs; - -interface SchemaConfigParams { - precision?: number; - useGeocentroid?: boolean; -} - -export interface SchemaConfig { - accessor: number; - label: string; - format: SerializedFieldFormat; - params: SchemaConfigParams; - aggType: string; -} - -export interface Schemas { - metric: SchemaConfig[]; - bucket?: SchemaConfig[]; - geo_centroid?: any[]; - group?: any[]; - params?: any[]; - radius?: any[]; - segment?: any[]; - split_column?: SchemaConfig[]; - split_row?: SchemaConfig[]; - width?: any[]; - // catch all for schema name - [key: string]: any[] | undefined; -} -export interface BuildPipelineParams { - timefilter: TimefilterContract; - timeRange?: any; - abortSignal?: AbortSignal; -} - -export const getSchemas = ( - vis: Vis, - { timeRange, timefilter }: BuildPipelineParams -): Schemas => { - const createSchemaConfig = (accessor: number, agg: IAggConfig): SchemaConfig => { - if (isDateHistogramBucketAggConfig(agg)) { - agg.params.timeRange = timeRange; - const bounds = - agg.params.timeRange && agg.fieldIsTimeField() - ? timefilter.calculateBounds(agg.params.timeRange) - : undefined; - agg.buckets.setBounds(bounds); - agg.buckets.setInterval(agg.params.interval); - } - - const hasSubAgg = [ - 'derivative', - 'moving_avg', - 'serial_diff', - 'cumulative_sum', - 'sum_bucket', - 'avg_bucket', - 'min_bucket', - 'max_bucket', - ].includes(agg.type.name); - - const formatAgg = hasSubAgg - ? agg.params.customMetric || agg.aggConfigs.getRequestAggById(agg.params.metricAgg) - : agg; - - const params: SchemaConfigParams = {}; - - if (agg.type.name === 'geohash_grid') { - params.precision = agg.params.precision; - params.useGeocentroid = agg.params.useGeocentroid; - } - - const label = agg.makeLabel && agg.makeLabel(); - - return { - accessor, - format: formatAgg.toSerializedFieldFormat(), - params, - label, - aggType: agg.type.name, - }; - }; - - let cnt = 0; - const schemas: Schemas = { - metric: [], - }; - - if (!vis.data.aggs) { - return schemas; - } - - const responseAggs = vis.data.aggs.getResponseAggs().filter((agg: IAggConfig) => agg.enabled); - const isHierarchical = vis.isHierarchical(); - const metrics = responseAggs.filter((agg: IAggConfig) => agg.type.type === 'metrics'); - responseAggs.forEach((agg: IAggConfig) => { - let skipMetrics = false; - let schemaName = agg.schema; - if (!schemaName) { - if (agg.type.name === 'geo_centroid') { - schemaName = 'geo_centroid'; - } else { - cnt++; - return; - } - } - if (schemaName === 'split') { - // TODO: We should check if there's a better way then casting to `any` here - schemaName = `split_${(vis.params as any).row ? 'row' : 'column'}`; - skipMetrics = responseAggs.length - metrics.length > 1; - } - if (!schemas[schemaName]) { - schemas[schemaName] = []; - } - if (!isHierarchical || agg.type.type !== 'metrics') { - schemas[schemaName]!.push(createSchemaConfig(cnt++, agg)); - } - if (isHierarchical && (agg.type.type !== 'metrics' || metrics.length === responseAggs.length)) { - metrics.forEach((metric: any) => { - const schemaConfig = createSchemaConfig(cnt++, metric); - if (!skipMetrics) { - schemas.metric.push(schemaConfig); - } - }); - } - }); - return schemas; -}; - -export const prepareJson = (variable: string, data?: object): string => { - if (data === undefined) { - return ''; - } - return `${variable}='${JSON.stringify(data).replace(/\\/g, `\\\\`).replace(/'/g, `\\'`)}' `; -}; - -export const escapeString = (data: string): string => { - return data.replace(/\\/g, `\\\\`).replace(/'/g, `\\'`); -}; - -export const prepareString = (variable: string, data?: string): string => { - if (data === undefined) { - return ''; - } - return `${variable}='${escapeString(data)}' `; -}; - -export const prepareValue = (variable: string, data: any, raw: boolean = false) => { - if (data === undefined) { - return ''; - } - if (raw) { - return `${variable}=${data} `; - } - switch (typeof data) { - case 'string': - return prepareString(variable, data); - case 'object': - return prepareJson(variable, data); - default: - return `${variable}=${data} `; - } -}; - -export const prepareDimension = (variable: string, data: any) => { - if (data === undefined) { - return ''; - } - - let expr = `${variable}={visdimension ${data.accessor} `; - if (data.format) { - expr += prepareValue('format', data.format.id); - expr += prepareJson('formatParams', data.format.params); - } - expr += '} '; - - return expr; -}; - -export const buildPipeline = async (vis: Vis, params: BuildPipelineParams) => { - const { indexPattern, searchSource } = vis.data; - const query = searchSource!.getField('query'); - const filters = searchSource!.getField('filter'); - const { uiState, title } = vis; - - // context - let pipeline = `kibana | kibana_context `; - if (query) { - pipeline += prepareJson('query', query); - } - if (filters) { - pipeline += prepareJson('filters', filters); - } - if (vis.data.savedSearchId) { - pipeline += prepareString('savedSearchId', vis.data.savedSearchId); - } - pipeline += '| '; - - if (vis.type.toExpressionAst) { - const visAst = await vis.type.toExpressionAst(vis, params); - pipeline += formatExpression(visAst); - } else { - // request handler - if (vis.type.requestHandler === 'courier') { - pipeline += `esaggs - index={indexPatternLoad ${prepareString('id', indexPattern!.id)}} - metricsAtAllLevels=${vis.isHierarchical()} - partialRows=${vis.params.showPartialRows || false} `; - if (vis.data.aggs) { - vis.data.aggs.aggs.forEach((agg) => { - const ast = agg.toExpressionAst(); - if (ast) { - pipeline += `aggs={${buildExpression(ast).toString()}} `; - } - }); - } - pipeline += `| `; - } else { - const schemas = getSchemas(vis, params); - const visConfig = { ...vis.params }; - visConfig.dimensions = schemas; - visConfig.title = title; - pipeline += `visualization type='${vis.type.name}' - ${prepareJson('visConfig', visConfig)} - ${prepareJson('uiState', uiState)} - metricsAtAllLevels=${vis.isHierarchical()} - partialRows=${vis.params.showPartialRows || false} `; - if (indexPattern) { - pipeline += `${prepareString('index', indexPattern.id)} `; - if (vis.data.aggs) { - pipeline += `${prepareJson('aggConfigs', vis.data.aggs!.aggs)}`; - } - } - } - } - - return pipeline; -}; diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index a8bf3b1ff3eb9..4f9fd53125847 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -22,7 +22,6 @@ import { savedObjectsPluginMock } from '../../../plugins/saved_objects/public/mo const createSetupContract = (): VisualizationsSetup => ({ createBaseVisualization: jest.fn(), - createReactVisualization: jest.fn(), registerAlias: jest.fn(), hideTypes: jest.fn(), }); diff --git a/src/plugins/visualizations/public/plugin.ts b/src/plugins/visualizations/public/plugin.ts index 8a82b36f37caf..24514dde10cda 100644 --- a/src/plugins/visualizations/public/plugin.ts +++ b/src/plugins/visualizations/public/plugin.ts @@ -20,15 +20,12 @@ import { TypesService, TypesSetup, TypesStart } from './vis_types'; import { setUISettings, setTypes, - setI18n, setApplication, setCapabilities, setHttp, - setIndexPatterns, setSearch, setSavedObjects, setUsageCollector, - setFilterManager, setExpressions, setUiActions, setSavedVisualizationsLoader, @@ -47,8 +44,6 @@ import { } from './embeddable'; import { ExpressionsSetup, ExpressionsStart } from '../../expressions/public'; import { EmbeddableSetup, EmbeddableStart } from '../../embeddable/public'; -import { visualization as visualizationFunction } from './expressions/visualization_function'; -import { visualization as visualizationRenderer } from './expressions/visualization_renderer'; import { range as rangeExpressionFunction } from './expression_functions/range'; import { visDimension as visDimensionExpressionFunction } from './expression_functions/vis_dimension'; import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../plugins/data/public'; @@ -138,8 +133,6 @@ export class VisualizationsPlugin setUISettings(core.uiSettings); setUsageCollector(usageCollection); - expressions.registerFunction(visualizationFunction); - expressions.registerRenderer(visualizationRenderer); expressions.registerFunction(rangeExpressionFunction); expressions.registerFunction(visDimensionExpressionFunction); const embeddableFactory = new VisualizeEmbeddableFactory({ start }); @@ -155,7 +148,6 @@ export class VisualizationsPlugin { data, expressions, uiActions, embeddable, dashboard, savedObjects }: VisualizationsStartDeps ): VisualizationsStart { const types = this.types.start(); - setI18n(core.i18n); setTypes(types); setEmbeddable(embeddable); setApplication(core.application); @@ -163,9 +155,7 @@ export class VisualizationsPlugin setHttp(core.http); setSavedObjects(core.savedObjects); setDocLinks(core.docLinks); - setIndexPatterns(data.indexPatterns); setSearch(data.search); - setFilterManager(data.query.filterManager); setExpressions(expressions); setUiActions(uiActions); setTimeFilter(data.query.timefilter.timefilter); diff --git a/src/plugins/visualizations/public/services.ts b/src/plugins/visualizations/public/services.ts index dd7d0941e7378..30cc514e48de4 100644 --- a/src/plugins/visualizations/public/services.ts +++ b/src/plugins/visualizations/public/services.ts @@ -11,7 +11,6 @@ import { Capabilities, ChromeStart, HttpStart, - I18nStart, IUiSettingsClient, OverlayStart, SavedObjectsStart, @@ -19,12 +18,7 @@ import { } from '../../../core/public'; import { TypesStart } from './vis_types'; import { createGetterSetter } from '../../../plugins/kibana_utils/public'; -import { - DataPublicPluginStart, - FilterManager, - IndexPatternsContract, - TimefilterContract, -} from '../../../plugins/data/public'; +import { DataPublicPluginStart, TimefilterContract } from '../../../plugins/data/public'; import { UsageCollectionSetup } from '../../../plugins/usage_collection/public'; import { ExpressionsStart } from '../../../plugins/expressions/public'; import { UiActionsStart } from '../../../plugins/ui_actions/public'; @@ -48,20 +42,10 @@ export const [getSavedObjects, setSavedObjects] = createGetterSetter('Types'); -export const [getI18n, setI18n] = createGetterSetter('I18n'); - export const [getDocLinks, setDocLinks] = createGetterSetter('DocLinks'); -export const [getFilterManager, setFilterManager] = createGetterSetter( - 'FilterManager' -); - export const [getTimeFilter, setTimeFilter] = createGetterSetter('TimeFilter'); -export const [getIndexPatterns, setIndexPatterns] = createGetterSetter( - 'IndexPatterns' -); - export const [getSearch, setSearch] = createGetterSetter('Search'); export const [getUsageCollector, setUsageCollector] = createGetterSetter( diff --git a/src/plugins/visualizations/public/types.ts b/src/plugins/visualizations/public/types.ts index dc9ca49840561..3a751c92f3ae7 100644 --- a/src/plugins/visualizations/public/types.ts +++ b/src/plugins/visualizations/public/types.ts @@ -7,26 +7,27 @@ */ import { SavedObject } from '../../../plugins/saved_objects/public'; -import { SearchSourceFields, TimefilterContract } from '../../../plugins/data/public'; +import { + AggConfigOptions, + IAggConfigs, + SearchSourceFields, + TimefilterContract, +} from '../../../plugins/data/public'; import { ExpressionAstExpression } from '../../expressions/public'; import { SerializedVis, Vis } from './vis'; -import { ExprVis } from './expressions/vis'; -import { SavedVisState, VisParams } from '../common/types'; +import { PersistedState } from './persisted_state'; +import { VisParams } from '../common'; export { Vis, SerializedVis, VisParams }; -export interface VisualizationController { - render(visData: any, visParams: any): Promise; - destroy(): void; - isLoaded?(): Promise | void; +export interface SavedVisState { + title: string; + type: string; + params: VisParams; + aggs: AggConfigOptions[]; } -export type VisualizationControllerConstructor = new ( - el: HTMLElement, - vis: ExprVis -) => VisualizationController; - export interface ISavedVis { id?: string; title: string; @@ -40,13 +41,6 @@ export interface ISavedVis { export interface VisSavedObject extends SavedObject, ISavedVis {} -export interface VisResponseValue { - visType: string; - visData: object; - visConfig: object; - params?: object; -} - export interface VisToExpressionAstParams { timefilter: TimefilterContract; timeRange?: any; @@ -57,3 +51,15 @@ export type VisToExpressionAst = ( vis: Vis, params: VisToExpressionAstParams ) => Promise | ExpressionAstExpression; + +export interface VisEditorOptionsProps { + aggs: IAggConfigs; + hasHistogramAgg: boolean; + isTabSelected: boolean; + stateParams: VisParamType; + vis: Vis; + uiState: PersistedState; + setValue(paramName: T, value: VisParamType[T]): void; + setValidity(isValid: boolean): void; + setTouched(isTouched: boolean): void; +} diff --git a/src/plugins/visualizations/public/vis.ts b/src/plugins/visualizations/public/vis.ts index 56a151fb82ed3..ab44c361bd5bd 100644 --- a/src/plugins/visualizations/public/vis.ts +++ b/src/plugins/visualizations/public/vis.ts @@ -22,7 +22,6 @@ import { i18n } from '@kbn/i18n'; import { PersistedState } from './persisted_state'; import { getTypes, getAggs, getSearch, getSavedSearchLoader } from './services'; -import { VisType } from './vis_types'; import { IAggConfigs, IndexPattern, @@ -30,6 +29,7 @@ import { AggConfigOptions, SearchSourceFields, } from '../../../plugins/data/public'; +import { BaseVisType } from './vis_types'; import { VisParams } from '../common/types'; export interface SerializedVisData { @@ -71,14 +71,11 @@ const getSearchSource = async (inputSearchSource: ISearchSource, savedSearchId?: type PartialVisState = Assign }>; export class Vis { - public readonly type: VisType; + public readonly type: BaseVisType; public readonly id?: string; public title: string = ''; public description: string = ''; public params: TVisParams; - // Session state is for storing information that is transitory, and will not be saved with the visualization. - // For instance, map bounds, which depends on the view port, browser window size, etc. - public sessionState: Record = {}; public data: VisData = {}; public readonly uiState: PersistedState; diff --git a/src/plugins/visualizations/public/vis_schemas.ts b/src/plugins/visualizations/public/vis_schemas.ts new file mode 100644 index 0000000000000..a00417b90baac --- /dev/null +++ b/src/plugins/visualizations/public/vis_schemas.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { SerializedFieldFormat } from '../../expressions/public'; +import { IAggConfig, search } from '../../data/public'; + +import { Vis, VisToExpressionAstParams } from './types'; + +const { isDateHistogramBucketAggConfig } = search.aggs; + +interface SchemaConfigParams { + precision?: number; + useGeocentroid?: boolean; +} + +export interface SchemaConfig { + accessor: number; + label: string; + format: SerializedFieldFormat; + params: SchemaConfigParams; + aggType: string; +} + +export interface Schemas { + metric: SchemaConfig[]; + bucket?: SchemaConfig[]; + geo_centroid?: any[]; + group?: any[]; + params?: any[]; + radius?: any[]; + segment?: any[]; + split_column?: SchemaConfig[]; + split_row?: SchemaConfig[]; + width?: any[]; + // catch all for schema name + [key: string]: any[] | undefined; +} + +export const getVisSchemas = ( + vis: Vis, + { timeRange, timefilter }: VisToExpressionAstParams +): Schemas => { + const createSchemaConfig = (accessor: number, agg: IAggConfig): SchemaConfig => { + if (isDateHistogramBucketAggConfig(agg)) { + agg.params.timeRange = timeRange; + const bounds = + agg.params.timeRange && agg.fieldIsTimeField() + ? timefilter.calculateBounds(agg.params.timeRange) + : undefined; + agg.buckets.setBounds(bounds); + agg.buckets.setInterval(agg.params.interval); + } + + const hasSubAgg = [ + 'derivative', + 'moving_avg', + 'serial_diff', + 'cumulative_sum', + 'sum_bucket', + 'avg_bucket', + 'min_bucket', + 'max_bucket', + ].includes(agg.type.name); + + const formatAgg = hasSubAgg + ? agg.params.customMetric || agg.aggConfigs.getRequestAggById(agg.params.metricAgg) + : agg; + + const params: SchemaConfigParams = {}; + + if (agg.type.name === 'geohash_grid') { + params.precision = agg.params.precision; + params.useGeocentroid = agg.params.useGeocentroid; + } + + const label = agg.makeLabel && agg.makeLabel(); + + return { + accessor, + format: formatAgg.toSerializedFieldFormat(), + params, + label, + aggType: agg.type.name, + }; + }; + + let cnt = 0; + const schemas: Schemas = { + metric: [], + }; + + if (!vis.data.aggs) { + return schemas; + } + + const responseAggs = vis.data.aggs.getResponseAggs().filter((agg: IAggConfig) => agg.enabled); + const isHierarchical = vis.isHierarchical(); + const metrics = responseAggs.filter((agg: IAggConfig) => agg.type.type === 'metrics'); + responseAggs.forEach((agg: IAggConfig) => { + let skipMetrics = false; + let schemaName = agg.schema; + if (!schemaName) { + if (agg.type.name === 'geo_centroid') { + schemaName = 'geo_centroid'; + } else { + cnt++; + return; + } + } + if (schemaName === 'split') { + // TODO: We should check if there's a better way then casting to `any` here + schemaName = `split_${(vis.params as any).row ? 'row' : 'column'}`; + skipMetrics = responseAggs.length - metrics.length > 1; + } + if (!schemas[schemaName]) { + schemas[schemaName] = []; + } + if (!isHierarchical || agg.type.type !== 'metrics') { + schemas[schemaName]!.push(createSchemaConfig(cnt++, agg)); + } + if (isHierarchical && (agg.type.type !== 'metrics' || metrics.length === responseAggs.length)) { + metrics.forEach((metric: any) => { + const schemaConfig = createSchemaConfig(cnt++, metric); + if (!skipMetrics) { + schemas.metric.push(schemaConfig); + } + }); + } + }); + return schemas; +}; diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.test.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.test.ts index 58670545f53e7..5091f9aca6b69 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.test.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.test.ts @@ -16,7 +16,16 @@ describe('BaseVisType', () => { name: 'test', title: 'test', description: 'test', - visualization: {} as any, + visConfig: { + defaults: {}, + }, + toExpressionAst: () => ({ + type: 'expression', + chain: [], + }), + editorConfig: { + editor: 'custom', + }, }); }).toThrow(); }); diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index e6e1704d45a8e..7425bf06bdfc2 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -9,54 +9,9 @@ import { defaultsDeep } from 'lodash'; import { VisParams } from '../types'; -import { VisType, VisTypeOptions, VisGroups } from './types'; +import { VisTypeDefinition, VisTypeOptions, VisGroups } from './types'; import { Schemas } from './schemas'; -interface CommonBaseVisTypeOptions - extends Pick< - VisType, - | 'description' - | 'getInfoMessage' - | 'getSupportedTriggers' - | 'hierarchicalData' - | 'icon' - | 'image' - | 'inspectorAdapters' - | 'name' - | 'requestHandler' - | 'responseHandler' - | 'setup' - | 'title' - >, - Pick< - Partial>, - | 'editorConfig' - | 'hidden' - | 'stage' - | 'getUsedIndexPattern' - | 'useCustomNoDataScreen' - | 'visConfig' - | 'group' - | 'titleInWizard' - | 'note' - > { - options?: Partial['options']>; -} - -interface ExpressionBaseVisTypeOptions extends CommonBaseVisTypeOptions { - toExpressionAst: VisType['toExpressionAst']; - visualization?: undefined; -} - -interface VisualizationBaseVisTypeOptions extends CommonBaseVisTypeOptions { - toExpressionAst?: undefined; - visualization: VisType['visualization']; -} - -export type BaseVisTypeOptions = - | ExpressionBaseVisTypeOptions - | VisualizationBaseVisTypeOptions; - const defaultOptions: VisTypeOptions = { showTimePicker: true, showQueryBar: true, @@ -65,7 +20,7 @@ const defaultOptions: VisTypeOptions = { hierarchicalData: false, // we should get rid of this i guess ? }; -export class BaseVisType implements VisType { +export class BaseVisType { public readonly name; public readonly title; public readonly description; @@ -76,23 +31,20 @@ export class BaseVisType implements VisType public readonly stage; public readonly group; public readonly titleInWizard; - public readonly options; - public readonly visualization; + public readonly options: VisTypeOptions; public readonly visConfig; public readonly editorConfig; public hidden; - public readonly requestHandler; - public readonly responseHandler; + public readonly requiresSearch; public readonly hierarchicalData; public readonly setup; public readonly getUsedIndexPattern; - public readonly useCustomNoDataScreen; public readonly inspectorAdapters; public readonly toExpressionAst; public readonly getInfoMessage; public readonly schemas; - constructor(opts: BaseVisTypeOptions) { + constructor(opts: VisTypeDefinition) { if (!opts.icon && !opts.image) { throw new Error('vis_type must define its icon or image'); } @@ -104,7 +56,6 @@ export class BaseVisType implements VisType this.title = opts.title; this.icon = opts.icon; this.image = opts.image; - this.visualization = opts.visualization; this.visConfig = defaultsDeep({}, opts.visConfig, { defaults: {} }); this.editorConfig = defaultsDeep({}, opts.editorConfig, { collections: {} }); this.options = defaultsDeep({}, opts.options, defaultOptions); @@ -112,20 +63,14 @@ export class BaseVisType implements VisType this.group = opts.group ?? VisGroups.AGGBASED; this.titleInWizard = opts.titleInWizard ?? ''; this.hidden = opts.hidden ?? false; - this.requestHandler = opts.requestHandler ?? 'courier'; - this.responseHandler = opts.responseHandler ?? 'none'; + this.requiresSearch = opts.requiresSearch ?? false; this.setup = opts.setup; this.hierarchicalData = opts.hierarchicalData ?? false; this.getUsedIndexPattern = opts.getUsedIndexPattern; - this.useCustomNoDataScreen = opts.useCustomNoDataScreen ?? false; this.inspectorAdapters = opts.inspectorAdapters; this.toExpressionAst = opts.toExpressionAst; this.getInfoMessage = opts.getInfoMessage; this.schemas = new Schemas(this.editorConfig?.schemas ?? []); } - - public get requiresSearch(): boolean { - return this.requestHandler !== 'none'; - } } diff --git a/src/plugins/visualizations/public/vis_types/index.ts b/src/plugins/visualizations/public/vis_types/index.ts index 0b3b1ec75cbe3..021c55e7a14bc 100644 --- a/src/plugins/visualizations/public/vis_types/index.ts +++ b/src/plugins/visualizations/public/vis_types/index.ts @@ -9,6 +9,5 @@ export * from './types_service'; export { Schemas } from './schemas'; export { VisGroups } from './types'; -export type { VisType, ISchemas, Schema } from './types'; -export type { BaseVisTypeOptions } from './base_vis_type'; -export type { ReactVisTypeOptions } from './react_vis_type'; +export { BaseVisType } from './base_vis_type'; +export type { VisTypeDefinition, ISchemas, Schema } from './types'; diff --git a/src/plugins/visualizations/public/vis_types/react_vis_controller.tsx b/src/plugins/visualizations/public/vis_types/react_vis_controller.tsx deleted file mode 100644 index 91e8db947f7e4..0000000000000 --- a/src/plugins/visualizations/public/vis_types/react_vis_controller.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import React from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; -import { VisualizationController } from '../types'; -import { getI18n, getUISettings } from '../services'; -import { ExprVis } from '../expressions/vis'; - -export class ReactVisController implements VisualizationController { - constructor(private element: HTMLElement, private vis: ExprVis) {} - - public render(visData: any, visParams: any): Promise { - const I18nContext = getI18n().Context; - - return new Promise((resolve, reject) => { - if (!this.vis.type || !this.vis.type.visConfig || !this.vis.type.visConfig.component) { - reject('Missing component for ReactVisType'); - } - - const Component = this.vis.type.visConfig.component; - const config = getUISettings(); - render( - - - , - this.element - ); - }); - } - - public destroy() { - unmountComponentAtNode(this.element); - } -} diff --git a/src/plugins/visualizations/public/vis_types/react_vis_type.test.ts b/src/plugins/visualizations/public/vis_types/react_vis_type.test.ts deleted file mode 100644 index 76d3321f2c92d..0000000000000 --- a/src/plugins/visualizations/public/vis_types/react_vis_type.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { cloneDeep } from 'lodash'; -import { ReactVisType } from './react_vis_type'; - -describe('React Vis Type', () => { - const visConfig = { - name: 'test', - title: 'test', - description: 'test', - icon: 'test', - visConfig: { component: 'test' }, - }; - - describe('initialization', () => { - it('should throw if component is not set', () => { - expect(() => { - const missingConfig = cloneDeep(visConfig); - // @ts-expect-error TS knows it's a required property - delete missingConfig.visConfig.component; - new ReactVisType(missingConfig); - }).toThrow(); - }); - - it('creates react controller', () => { - const visType = new ReactVisType(visConfig); - expect(visType.visualization).not.toBeUndefined(); - }); - }); -}); diff --git a/src/plugins/visualizations/public/vis_types/react_vis_type.ts b/src/plugins/visualizations/public/vis_types/react_vis_type.ts deleted file mode 100644 index 336599f67702d..0000000000000 --- a/src/plugins/visualizations/public/vis_types/react_vis_type.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * and the Server Side Public License, v 1; you may not use this file except in - * compliance with, at your election, the Elastic License or the Server Side - * Public License, v 1. - */ - -import { BaseVisType, BaseVisTypeOptions } from './base_vis_type'; -import { ReactVisController } from './react_vis_controller'; -import { VisType } from './types'; - -export type ReactVisTypeOptions = Omit< - BaseVisTypeOptions, - 'visualization' | 'toExpressionAst' ->; - -/** - * This class should only be used for visualizations not using the `toExpressionAst` with a custom renderer. - * If you implement a custom renderer you should just mount a react component inside this. - */ -export class ReactVisType - extends BaseVisType - implements VisType { - constructor(opts: ReactVisTypeOptions) { - super({ - ...opts, - visualization: ReactVisController, - }); - - if (!this.visConfig.component) { - throw new Error('Missing component for ReactVisType'); - } - } -} diff --git a/src/plugins/visualizations/public/vis_types/schemas.ts b/src/plugins/visualizations/public/vis_types/schemas.ts index 3ce38e68e7f32..50bf50a857815 100644 --- a/src/plugins/visualizations/public/vis_types/schemas.ts +++ b/src/plugins/visualizations/public/vis_types/schemas.ts @@ -37,7 +37,6 @@ export class Schemas implements ISchemas { group: AggGroupNames.Buckets, title: schema.name, aggFilter: '*', - editor: false, params: [], }); diff --git a/src/plugins/visualizations/public/vis_types/types.ts b/src/plugins/visualizations/public/vis_types/types.ts index b38c9e41d5c7b..7244aae64e963 100644 --- a/src/plugins/visualizations/public/vis_types/types.ts +++ b/src/plugins/visualizations/public/vis_types/types.ts @@ -7,10 +7,10 @@ */ import { IconType } from '@elastic/eui'; -import React, { ReactNode } from 'react'; +import { ReactNode } from 'react'; import { Adapters } from 'src/plugins/inspector'; import { IndexPattern, AggGroupNames, AggParam, AggGroupName } from '../../../data/public'; -import { Vis, VisParams, VisToExpressionAst, VisualizationControllerConstructor } from '../types'; +import { Vis, VisEditorOptionsProps, VisParams, VisToExpressionAst } from '../types'; export interface VisTypeOptions { showTimePicker: boolean; @@ -34,7 +34,6 @@ export interface ISchemas { export interface Schema { aggFilter: string[]; - editor: boolean | string; group: AggGroupName; max: number; min: number; @@ -49,11 +48,35 @@ export interface Schema { tooltip?: ReactNode; } +type DefaultEditorOptionsComponent = React.ComponentType< + VisEditorOptionsProps +>; + +interface DefaultEditorConfig { + // collections should moved directly into default editor in https://github.com/elastic/kibana/issues/84879 + collections?: { + [key: string]: Array<{ text: string; value: string }> | Array<{ id: string; label: string }>; + }; + enableAutoApply?: boolean; + defaultSize?: string; + optionsTemplate?: DefaultEditorOptionsComponent; + optionTabs?: Array<{ + name: string; + title: string; + editor: DefaultEditorOptionsComponent; + }>; + schemas?: Array>; +} + +interface CustomEditorConfig { + editor: string; +} + /** - * A visualization type representing one specific type of "classical" + * A visualization type definition representing a spec of one specific type of "classical" * visualizations (i.e. not Lens visualizations). */ -export interface VisType { +export interface VisTypeDefinition { /** * Visualization unique name */ @@ -69,7 +92,7 @@ export interface VisType { /** * If given, it will be diplayed on the wizard vis card as a note in italic. */ - readonly note: string; + readonly note?: string; /** * If given, it will return the supported triggers for this vis. */ @@ -82,8 +105,6 @@ export interface VisType { readonly getUsedIndexPattern?: (visParams: VisParams) => IndexPattern[] | Promise; readonly isAccessible?: boolean; - readonly requestHandler?: string | unknown; - readonly responseHandler?: string | unknown; /** * It is the visualization icon, displayed on the wizard. */ @@ -94,21 +115,27 @@ export interface VisType { readonly image?: string; /** * Describes the visualization stage + * @default 'production' */ - readonly stage: 'experimental' | 'beta' | 'production'; + readonly stage?: 'experimental' | 'beta' | 'production'; /** * Describes the experience group that the visualization belongs. * It can be on tools, aggregation based or promoted group. + * @default 'aggbased' */ - readonly group: VisGroups; + readonly group?: VisGroups; /** * If given, it will be displayed on the wizard instead of the title. * We use it because we want to differentiate the vis title from the * way it is presented on the wizard */ - readonly titleInWizard: string; - readonly requiresSearch: boolean; - readonly useCustomNoDataScreen: boolean; + readonly titleInWizard?: string; + /** + * The flag is necessary for aggregation based visualizations. + * When "true", an additional step on the vis creation wizard will be provided + * with the selection of a search source - an index pattern or a saved search. + */ + readonly requiresSearch?: boolean; readonly hierarchicalData?: boolean | ((vis: { params: TVisParams }) => boolean); readonly inspectorAdapters?: Adapters | (() => Adapters); /** @@ -118,18 +145,27 @@ export interface VisType { * of this type. */ readonly getInfoMessage?: (vis: Vis) => React.ReactNode; - - readonly toExpressionAst?: VisToExpressionAst; - readonly visualization?: VisualizationControllerConstructor; + /** + * Should be provided to expand base visualization expression with + * custom exprsesion chain, including render expression. + * Explicit renderer should be registered in expressions plugin to render your visualization. + */ + readonly toExpressionAst: VisToExpressionAst; readonly setup?: (vis: Vis) => Promise>; - hidden: boolean; + hidden?: boolean; - readonly schemas: ISchemas; + readonly options?: Partial; - readonly options: VisTypeOptions; - - // TODO: The following types still need to be refined properly. - readonly editorConfig: Record; + /** + * Config for the default editor. + * Custom editor can be specified. + */ + readonly editorConfig: DefaultEditorConfig | CustomEditorConfig; + /** + * Have the "defaults" prop with default params for a visualization. + * TODO: ideally should have next type: { defaults: TVisParams } , but currently + * have incosistencies in legacy visLib visualizations + */ readonly visConfig: Record; } diff --git a/src/plugins/visualizations/public/vis_types/types_service.ts b/src/plugins/visualizations/public/vis_types/types_service.ts index d26f5ca882b65..09f7f8f599f2c 100644 --- a/src/plugins/visualizations/public/vis_types/types_service.ts +++ b/src/plugins/visualizations/public/vis_types/types_service.ts @@ -7,9 +7,8 @@ */ import { visTypeAliasRegistry, VisTypeAlias } from './vis_type_alias_registry'; -import { BaseVisType, BaseVisTypeOptions } from './base_vis_type'; -import { ReactVisType, ReactVisTypeOptions } from './react_vis_type'; -import { VisType, VisGroups } from './types'; +import { BaseVisType } from './base_vis_type'; +import { VisTypeDefinition, VisGroups } from './types'; /** * Vis Types Service @@ -17,10 +16,10 @@ import { VisType, VisGroups } from './types'; * @internal */ export class TypesService { - private types: Record> = {}; + private types: Record> = {}; private unregisteredHiddenTypes: string[] = []; - private registerVisualization(visDefinition: VisType) { + private registerVisualization(visDefinition: BaseVisType) { if (this.unregisteredHiddenTypes.includes(visDefinition.name)) { visDefinition.hidden = true; } @@ -37,18 +36,10 @@ export class TypesService { * registers a visualization type * @param config - visualization type definition */ - createBaseVisualization: (config: BaseVisTypeOptions): void => { + createBaseVisualization: (config: VisTypeDefinition): void => { const vis = new BaseVisType(config); this.registerVisualization(vis); }, - /** - * registers a visualization which uses react for rendering - * @param config - visualization type definition - */ - createReactVisualization: (config: ReactVisTypeOptions): void => { - const vis = new ReactVisType(config); - this.registerVisualization(vis); - }, /** * registers a visualization alias * alias is a visualization type without implementation, it just redirects somewhere in kibana @@ -77,13 +68,13 @@ export class TypesService { * returns specific visualization or undefined if not found * @param {string} visualization - id of visualization to return */ - get: (visualization: string): VisType => { + get: (visualization: string): BaseVisType | undefined => { return this.types[visualization]; }, /** * returns all registered visualization types */ - all: (): VisType[] => { + all: (): BaseVisType[] => { return [...Object.values(this.types)]; }, /** @@ -119,6 +110,3 @@ export type TypesStart = ReturnType; /** @public types */ export { VisTypeAlias }; - -/** @public static code */ -// TODO once items are moved from ui/vis into this service diff --git a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.test.tsx b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.test.tsx index 053d36e89ad75..9e825982b9065 100644 --- a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.test.tsx +++ b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.test.tsx @@ -8,19 +8,13 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test/jest'; -import { TypesStart, VisType, VisGroups } from '../../vis_types'; +import { TypesStart, BaseVisType, VisGroups } from '../../vis_types'; import { AggBasedSelection } from './agg_based_selection'; describe('AggBasedSelection', () => { const defaultVisTypeParams = { hidden: false, - visualization: class Controller { - public render = jest.fn(); - public destroy = jest.fn(); - }, requiresSearch: false, - requestHandler: 'none', - responseHandler: 'none', }; const _visTypes = [ { @@ -50,22 +44,16 @@ describe('AggBasedSelection', () => { stage: 'production', ...defaultVisTypeParams, }, - ] as VisType[]; + ] as BaseVisType[]; const visTypes: TypesStart = { - get(id: string): VisType { - return _visTypes.find((vis) => vis.name === id) as VisType; - }, - all: () => { - return (_visTypes as unknown) as VisType[]; + get(id: string): BaseVisType { + return (_visTypes.find((vis) => vis.name === id) as unknown) as BaseVisType; }, + all: () => _visTypes, getAliases: () => [], unRegisterAlias: () => [], - getByGroup: (group: VisGroups) => { - return _visTypes.filter((type) => { - return type.group === group; - }) as VisType[]; - }, + getByGroup: (group: VisGroups) => _visTypes.filter((type) => type.group === group), }; beforeAll(() => { diff --git a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx index 1496f0c60f82d..f5013dddc5c79 100644 --- a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx +++ b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx @@ -25,17 +25,17 @@ import { } from '@elastic/eui'; import { memoizeLast } from '../../legacy/memoize'; -import type { VisType, TypesStart } from '../../vis_types'; +import type { BaseVisType, TypesStart } from '../../vis_types'; import { VisGroups } from '../../vis_types'; import { DialogNavigation } from '../dialog_navigation'; interface VisTypeListEntry { - type: VisType; + type: BaseVisType; highlighted: boolean; } interface AggBasedSelectionProps { - onVisTypeSelected: (visType: VisType) => void; + onVisTypeSelected: (visType: BaseVisType) => void; visTypesRegistry: TypesStart; toggleGroups: (flag: boolean) => void; } diff --git a/src/plugins/visualizations/public/wizard/group_selection/group_selection.test.tsx b/src/plugins/visualizations/public/wizard/group_selection/group_selection.test.tsx index 60857cc39661e..74163296e31fd 100644 --- a/src/plugins/visualizations/public/wizard/group_selection/group_selection.test.tsx +++ b/src/plugins/visualizations/public/wizard/group_selection/group_selection.test.tsx @@ -8,20 +8,14 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test/jest'; -import { TypesStart, VisType, VisGroups } from '../../vis_types'; +import { TypesStart, BaseVisType, VisGroups } from '../../vis_types'; import { GroupSelection } from './group_selection'; import { DocLinksStart } from '../../../../../core/public'; describe('GroupSelection', () => { const defaultVisTypeParams = { hidden: false, - visualization: class Controller { - public render = jest.fn(); - public destroy = jest.fn(); - }, requiresSearch: false, - requestHandler: 'none', - responseHandler: 'none', }; const _visTypes = [ { @@ -64,22 +58,22 @@ describe('GroupSelection', () => { aliasPath: '#/anotherUrl', promotion: true, } as unknown, - ] as VisType[]; + ] as BaseVisType[]; - const visTypesRegistry = (visTypes: VisType[]): TypesStart => { + const visTypesRegistry = (visTypes: BaseVisType[]): TypesStart => { return { - get(id: string): VisType { - return (visTypes.find((vis) => vis.name === id) as unknown) as VisType; + get(id: string): BaseVisType { + return (visTypes.find((vis) => vis.name === id) as unknown) as BaseVisType; }, all: () => { - return (visTypes as unknown) as VisType[]; + return (visTypes as unknown) as BaseVisType[]; }, getAliases: () => [], unRegisterAlias: () => [], getByGroup: (group: VisGroups) => { return (visTypes.filter((type) => { return type.group === group; - }) as unknown) as VisType[]; + }) as unknown) as BaseVisType[]; }, }; }; @@ -142,7 +136,7 @@ describe('GroupSelection', () => { }; const wrapper = mountWithIntl( { }; const wrapper = mountWithIntl( { }; const wrapper = mountWithIntl( { it('should sort promoted visualizations first', () => { const wrapper = mountWithIntl( { it('should render disabled aliases with a disabled class', () => { const wrapper = mountWithIntl( { it('should render a basic badge with link for disabled aliases with promoTooltip', () => { const wrapper = mountWithIntl( { }; const wrapper = mountWithIntl( { }; const wrapper = mountWithIntl( void; + onVisTypeSelected: (visType: BaseVisType | VisTypeAlias) => void; visTypesRegistry: TypesStart; docLinks: DocLinksStart; toggleGroups: (flag: boolean) => void; @@ -43,12 +43,12 @@ interface GroupSelectionProps { } interface VisCardProps { - onVisTypeSelected: (visType: VisType | VisTypeAlias) => void; - visType: VisType | VisTypeAlias; + onVisTypeSelected: (visType: BaseVisType | VisTypeAlias) => void; + visType: BaseVisType | VisTypeAlias; showExperimental?: boolean | undefined; } -function isVisTypeAlias(type: VisType | VisTypeAlias): type is VisTypeAlias { +function isVisTypeAlias(type: BaseVisType | VisTypeAlias): type is VisTypeAlias { return 'aliasPath' in type; } diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx index baaed6d4ea8bf..c8a3c81f517ea 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.test.tsx @@ -8,21 +8,16 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test/jest'; -import { TypesStart, VisType, VisGroups } from '../vis_types'; +import { TypesStart, VisGroups } from '../vis_types'; import NewVisModal from './new_vis_modal'; import { ApplicationStart, SavedObjectsStart, DocLinksStart } from '../../../../core/public'; import { embeddablePluginMock } from '../../../embeddable/public/mocks'; +import { BaseVisType } from '../vis_types'; describe('NewVisModal', () => { const defaultVisTypeParams = { hidden: false, - visualization: class Controller { - public render = jest.fn(); - public destroy = jest.fn(); - }, requiresSearch: false, - requestHandler: 'none', - responseHandler: 'none', }; const _visTypes = [ { @@ -61,21 +56,15 @@ describe('NewVisModal', () => { stage: 'production', ...defaultVisTypeParams, }, - ]; + ] as BaseVisType[]; const visTypes: TypesStart = { - get(id: string): VisType { - return (_visTypes.find((vis) => vis.name === id) as unknown) as VisType; - }, - all: () => { - return (_visTypes as unknown) as VisType[]; + get(id: string): BaseVisType { + return (_visTypes.find((vis) => vis.name === id) as unknown) as BaseVisType; }, + all: () => _visTypes, getAliases: () => [], unRegisterAlias: () => [], - getByGroup: (group: VisGroups) => { - return (_visTypes.filter((type) => { - return type.group === group; - }) as unknown) as VisType[]; - }, + getByGroup: (group: VisGroups) => _visTypes.filter((type) => type.group === group), }; const addBasePath = (url: string) => `testbasepath${url}`; const settingsGet = jest.fn(); diff --git a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx index 2a9641607d17a..b0be73e486d6c 100644 --- a/src/plugins/visualizations/public/wizard/new_vis_modal.tsx +++ b/src/plugins/visualizations/public/wizard/new_vis_modal.tsx @@ -21,7 +21,7 @@ import { import { SearchSelection } from './search_selection'; import { GroupSelection } from './group_selection'; import { AggBasedSelection } from './agg_based_selection'; -import type { TypesStart, VisType, VisTypeAlias } from '../vis_types'; +import type { TypesStart, BaseVisType, VisTypeAlias } from '../vis_types'; import { UsageCollectionSetup } from '../../../../plugins/usage_collection/public'; import { EmbeddableStateTransfer } from '../../../embeddable/public'; import { VISUALIZE_ENABLE_LABS_SETTING } from '../../common/constants'; @@ -46,7 +46,7 @@ interface TypeSelectionProps { interface TypeSelectionState { showSearchVisModal: boolean; showGroups: boolean; - visType?: VisType; + visType?: BaseVisType; } // TODO: redirect logic is specific to visualise & dashboard @@ -129,7 +129,7 @@ class NewVisModal extends React.Component { + private onVisTypeSelected = (visType: BaseVisType | VisTypeAlias) => { if (!('aliasPath' in visType) && visType.requiresSearch && visType.options.showIndexSelection) { this.setState({ showSearchVisModal: true, @@ -144,7 +144,11 @@ class NewVisModal extends React.Component void; - visType: VisType; + visType: BaseVisType; uiSettings: IUiSettingsClient; savedObjects: SavedObjectsStart; goBack: () => void; diff --git a/test/interpreter_functional/snapshots/baseline/combined_test3.json b/test/interpreter_functional/snapshots/baseline/combined_test3.json index 2aa601a8d3631..64b1052552c8f 100644 --- a/test/interpreter_functional/snapshots/baseline/combined_test3.json +++ b/test/interpreter_functional/snapshots/baseline/combined_test3.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/final_output_test.json b/test/interpreter_functional/snapshots/baseline/final_output_test.json index 2aa601a8d3631..64b1052552c8f 100644 --- a/test/interpreter_functional/snapshots/baseline/final_output_test.json +++ b/test/interpreter_functional/snapshots/baseline/final_output_test.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_all_data.json b/test/interpreter_functional/snapshots/baseline/metric_all_data.json index dd779800cd452..0e1e5a723373f 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_all_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_all_data.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_invalid_data.json b/test/interpreter_functional/snapshots/baseline/metric_invalid_data.json index 0a47cdb8ff74a..c7b4a0325dc91 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_invalid_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_invalid_data.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[],"meta":{},"rows":[],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[],"meta":{},"rows":[],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json b/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json index 992d667fdce9f..fc8622a818dec 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_multi_metric_data.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_percentage_mode.json b/test/interpreter_functional/snapshots/baseline/metric_percentage_mode.json index 031c9f9ea5504..95c011f9259b9 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_percentage_mode.json +++ b/test/interpreter_functional/snapshots/baseline/metric_percentage_mode.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json b/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json index 8c6fde201c8f1..f4a8cd1f14e18 100644 --- a/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json +++ b/test/interpreter_functional/snapshots/baseline/metric_single_metric_data.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/partial_test_2.json b/test/interpreter_functional/snapshots/baseline/partial_test_2.json index 2aa601a8d3631..64b1052552c8f 100644 --- a/test/interpreter_functional/snapshots/baseline/partial_test_2.json +++ b/test/interpreter_functional/snapshots/baseline/partial_test_2.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/baseline/step_output_test3.json b/test/interpreter_functional/snapshots/baseline/step_output_test3.json index 2aa601a8d3631..64b1052552c8f 100644 --- a/test/interpreter_functional/snapshots/baseline/step_output_test3.json +++ b/test/interpreter_functional/snapshots/baseline/step_output_test3.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/combined_test3.json b/test/interpreter_functional/snapshots/session/combined_test3.json index 2aa601a8d3631..64b1052552c8f 100644 --- a/test/interpreter_functional/snapshots/session/combined_test3.json +++ b/test/interpreter_functional/snapshots/session/combined_test3.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/final_output_test.json b/test/interpreter_functional/snapshots/session/final_output_test.json index 2aa601a8d3631..64b1052552c8f 100644 --- a/test/interpreter_functional/snapshots/session/final_output_test.json +++ b/test/interpreter_functional/snapshots/session/final_output_test.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_all_data.json b/test/interpreter_functional/snapshots/session/metric_all_data.json index dd779800cd452..0e1e5a723373f 100644 --- a/test/interpreter_functional/snapshots/session/metric_all_data.json +++ b/test/interpreter_functional/snapshots/session/metric_all_data.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":2,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_invalid_data.json b/test/interpreter_functional/snapshots/session/metric_invalid_data.json index 0a47cdb8ff74a..c7b4a0325dc91 100644 --- a/test/interpreter_functional/snapshots/session/metric_invalid_data.json +++ b/test/interpreter_functional/snapshots/session/metric_invalid_data.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[],"meta":{},"rows":[],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[],"meta":{},"rows":[],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json b/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json index 992d667fdce9f..fc8622a818dec 100644 --- a/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json +++ b/test/interpreter_functional/snapshots/session/metric_multi_metric_data.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},{"accessor":1,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_percentage_mode.json b/test/interpreter_functional/snapshots/session/metric_percentage_mode.json index 031c9f9ea5504..95c011f9259b9 100644 --- a/test/interpreter_functional/snapshots/session/metric_percentage_mode.json +++ b/test/interpreter_functional/snapshots/session/metric_percentage_mode.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":1000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":true,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/metric_single_metric_data.json b/test/interpreter_functional/snapshots/session/metric_single_metric_data.json index 8c6fde201c8f1..f4a8cd1f14e18 100644 --- a/test/interpreter_functional/snapshots/session/metric_single_metric_data.json +++ b/test/interpreter_functional/snapshots/session/metric_single_metric_data.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"metrics":[{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"},{"id":"col-2-1","meta":{"field":"bytes","index":"logstash-*","params":{"id":"bytes","params":null},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{"field":"bytes"},"schema":"metric","type":"max"},"type":"number"},"name":"Max bytes"}],"rows":[{"col-0-2":"200","col-1-1":12891,"col-2-1":19986},{"col-0-2":"404","col-1-1":696,"col-2-1":19881},{"col-0-2":"503","col-1-1":417,"col-2-1":0}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/partial_test_2.json b/test/interpreter_functional/snapshots/session/partial_test_2.json index 2aa601a8d3631..64b1052552c8f 100644 --- a/test/interpreter_functional/snapshots/session/partial_test_2.json +++ b/test/interpreter_functional/snapshots/session/partial_test_2.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/step_output_test3.json b/test/interpreter_functional/snapshots/session/step_output_test3.json index 2aa601a8d3631..64b1052552c8f 100644 --- a/test/interpreter_functional/snapshots/session/step_output_test3.json +++ b/test/interpreter_functional/snapshots/session/step_output_test3.json @@ -1 +1 @@ -{"as":"metric_vis","type":"render","value":{"params":{"listenOnChange":true},"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file +{"as":"metric_vis","type":"render","value":{"visConfig":{"dimensions":{"bucket":{"accessor":0,"format":{"id":"string","params":{}},"type":"vis_dimension"},"metrics":[{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"}]},"metric":{"colorSchema":"Green to Red","colorsRange":[{"from":0,"to":10000,"type":"range"}],"invertColors":false,"labels":{"show":true},"metricColorMode":"None","percentageMode":false,"style":{"bgColor":false,"bgFill":"#000","fontSize":60,"labelColor":false,"subText":""},"useRanges":false}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"metric"}} \ No newline at end of file diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/kibana.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/kibana.json index 622cbd80090ba..33c8f3238dc47 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/kibana.json +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/kibana.json @@ -3,6 +3,7 @@ "version": "0.0.1", "kibanaVersion": "kibana", "requiredPlugins": [ + "expressions", "visualizations" ], "server": false, diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/plugin.ts b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/plugin.ts index 7de3965d66d35..d4a7a32ba42dd 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/plugin.ts +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/plugin.ts @@ -7,25 +7,42 @@ */ import { CoreSetup, Plugin } from 'kibana/public'; -import { VisualizationsSetup } from '../../../../../src/plugins/visualizations/public'; +import { VisualizationsSetup } from 'src/plugins/visualizations/public'; +import { Plugin as ExpressionsPlugin } from '../../../../../src/plugins/expressions/public'; + import { SelfChangingEditor } from './self_changing_vis/self_changing_editor'; -import { SelfChangingComponent } from './self_changing_vis/self_changing_components'; +import { selfChangingVisFn, SelfChangingVisParams } from './self_changing_vis_fn'; +import { selfChangingVisRenderer } from './self_changing_vis_renderer'; +import { toExpressionAst } from './to_ast'; export interface SetupDependencies { + expressions: ReturnType; visualizations: VisualizationsSetup; } export class CustomVisualizationsPublicPlugin implements Plugin { - public setup(core: CoreSetup, setupDeps: SetupDependencies) { - setupDeps.visualizations.createReactVisualization({ + public setup(core: CoreSetup, { expressions, visualizations }: SetupDependencies) { + /** + * Register an expression function with type "render" for your visualization + */ + expressions.registerFunction(selfChangingVisFn); + + /** + * Register a renderer for your visualization + */ + expressions.registerRenderer(selfChangingVisRenderer); + + /** + * Create the visualization type with definition + */ + visualizations.createBaseVisualization({ name: 'self_changing_vis', title: 'Self Changing Vis', icon: 'controlsHorizontal', description: 'This visualization is able to change its own settings, that you could also set in the editor.', visConfig: { - component: SelfChangingComponent, defaults: { counter: 0, }, @@ -39,7 +56,7 @@ export class CustomVisualizationsPublicPlugin }, ], }, - requestHandler: 'none', + toExpressionAst, }); } diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_components.tsx b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_components.tsx index 3b3e57bff8aa1..7409bc48d3bc3 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_components.tsx +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_components.tsx @@ -7,14 +7,13 @@ */ import React, { useEffect } from 'react'; - import { EuiBadge } from '@elastic/eui'; +import { SelfChangingVisParams } from '../self_changing_vis_fn'; + interface SelfChangingComponentProps { - renderComplete: () => {}; - visParams: { - counter: number; - }; + renderComplete(): void; + visParams: SelfChangingVisParams; } export function SelfChangingComponent(props: SelfChangingComponentProps) { diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_editor.tsx b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_editor.tsx index ff3fd63e5d4aa..ad651ab55220d 100644 --- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_editor.tsx +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis/self_changing_editor.tsx @@ -9,13 +9,13 @@ import React from 'react'; import { EuiFieldNumber, EuiFormRow } from '@elastic/eui'; -import { VisOptionsProps } from 'src/plugins/vis_default_editor/public/vis_options_props'; +import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; interface CounterParams { counter: number; } -export class SelfChangingEditor extends React.Component> { +export class SelfChangingEditor extends React.Component> { onCounterChange = (ev: any) => { this.props.setValue('counter', parseInt(ev.target.value, 10)); }; diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis_fn.ts b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis_fn.ts new file mode 100644 index 0000000000000..28bcc27f71ec9 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis_fn.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { ExpressionFunctionDefinition, Render } from 'src/plugins/expressions/public'; +import { KibanaContext } from 'src/plugins/data/public'; + +export interface SelfChangingVisParams { + counter: number; +} + +export interface SelfChangingVisRenderValue { + visParams: { + counter: number; + }; +} + +type Output = Promise>; + +export type SelfChangingVisExpressionFunctionDefinition = ExpressionFunctionDefinition< + 'self_changing_vis', + KibanaContext, + SelfChangingVisParams, + Output +>; + +export const selfChangingVisFn: SelfChangingVisExpressionFunctionDefinition = { + name: 'self_changing_vis', + type: 'render', + inputTypes: ['kibana_context'], + help: + 'The expression function definition should be registered for a custom visualization to be rendered', + args: { + counter: { + types: ['number'], + default: 0, + help: 'Visualization only argument with type number', + }, + }, + async fn(input, args) { + /** + * You can do any calculation you need before rendering. + * The function can also do asynchronous operations, e.x.: + * + const calculatedCounter = await new Promise((resolve) => + setTimeout(() => { + resolve(args.counter * 2); + }, 3000) + ); + */ + + return { + type: 'render', + as: 'self_changing_vis', + value: { + visParams: { + counter: args.counter, + }, + }, + }; + }, +}; diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis_renderer.tsx b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis_renderer.tsx new file mode 100644 index 0000000000000..ea24e6c294880 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/self_changing_vis_renderer.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; + +import { ExpressionRenderDefinition } from 'src/plugins/expressions'; +import { SelfChangingComponent } from './self_changing_vis/self_changing_components'; +import { SelfChangingVisRenderValue } from './self_changing_vis_fn'; + +export const selfChangingVisRenderer: ExpressionRenderDefinition = { + name: 'self_changing_vis', + reuseDomNode: true, + render: (domNode, { visParams }, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render(, domNode); + }, +}; diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/to_ast.ts b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/to_ast.ts new file mode 100644 index 0000000000000..0f7ecb7954d15 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/public/to_ast.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * and the Server Side Public License, v 1; you may not use this file except in + * compliance with, at your election, the Elastic License or the Server Side + * Public License, v 1. + */ + +import { VisToExpressionAst } from 'src/plugins/visualizations/public'; +import { + buildExpression, + buildExpressionFunction, +} from '../../../../../src/plugins/expressions/public'; +import { + SelfChangingVisExpressionFunctionDefinition, + SelfChangingVisParams, +} from './self_changing_vis_fn'; + +export const toExpressionAst: VisToExpressionAst = (vis) => { + const { counter } = vis.params; + + const selfChangingVis = buildExpressionFunction( + 'self_changing_vis', + { counter } + ); + + const ast = buildExpression([selfChangingVis]); + + return ast.toAst(); +}; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ef2149c4931fa..9d8951b03f39a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4693,7 +4693,6 @@ "visualizations.function.visDimension.format.help": "フォーマット", "visualizations.function.visDimension.formatParams.help": "フォーマットパラメーター", "visualizations.function.visDimension.help": "visConfig ディメンションオブジェクトを生成します", - "visualizations.functions.visualization.help": "シンプルなビジュアライゼーションです", "visualizations.initializeWithoutIndexPatternErrorMessage": "インデックスパターンなしで集約を初期化しようとしています", "visualizations.newVisWizard.aggBasedGroupDescription": "クラシック Visualize ライブラリを使用して、アグリゲーションに基づいてグラフを作成します。", "visualizations.newVisWizard.aggBasedGroupTitle": "アグリゲーションに基づく", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 08d064ce8a05c..afa8c6d4be51a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4698,7 +4698,6 @@ "visualizations.function.visDimension.format.help": "格式", "visualizations.function.visDimension.formatParams.help": "格式参数", "visualizations.function.visDimension.help": "生成 visConfig 维度对象", - "visualizations.functions.visualization.help": "简单可视化", "visualizations.initializeWithoutIndexPatternErrorMessage": "正在尝试在不使用索引模式的情况下初始化聚合", "visualizations.newVisWizard.aggBasedGroupDescription": "使用我们的经典可视化库,基于聚合创建图表。", "visualizations.newVisWizard.aggBasedGroupTitle": "基于聚合", From 1994c5bfd95c3a102e55e667ea75f28a851bc8d0 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 26 Jan 2021 09:49:04 +0100 Subject: [PATCH 07/21] [Core] remove unused "pageNavigation" setting (#89160) * remove unused advanced setting * remove docs --- docs/management/advanced-options.asciidoc | 5 ----- .../ui_settings/settings/navigation.test.ts | 14 ------------- .../server/ui_settings/settings/navigation.ts | 20 ------------------- .../server/collectors/management/schema.ts | 1 - src/plugins/telemetry/schema/oss_plugins.json | 3 --- .../translations/translations/ja-JP.json | 4 ---- .../translations/translations/zh-CN.json | 4 ---- 7 files changed, 51 deletions(-) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index c2306b80734d8..bf4f7d9d82704 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -134,11 +134,6 @@ The maximum numbers of buckets that a single data source can return. This might arise when the user selects a short interval (for example, 1s) for a long time period (1 year). -[[pagenavigation]]`pageNavigation`:: -The style of navigation menu for Kibana. Choices are Legacy, the legacy style -where every plugin is represented in the nav, and Modern, a new format that -bundles related plugins together in flyaway nested navigation. - [[query-allowleadingwildcards]]`query:allowLeadingWildcards`:: Allows a wildcard (*) as the first character in a query clause. Only applies when experimental query features are enabled in the query bar. To disallow diff --git a/src/core/server/ui_settings/settings/navigation.test.ts b/src/core/server/ui_settings/settings/navigation.test.ts index 1ba81b4e79f46..0e6fbdfdbdb6e 100644 --- a/src/core/server/ui_settings/settings/navigation.test.ts +++ b/src/core/server/ui_settings/settings/navigation.test.ts @@ -28,18 +28,4 @@ describe('navigation settings', () => { ); }); }); - - describe('pageNavigation', () => { - const validate = getValidationFn(navigationSettings.pageNavigation); - - it('should only accept valid values', () => { - expect(() => validate('modern')).not.toThrow(); - expect(() => validate('legacy')).not.toThrow(); - expect(() => validate('invalid')).toThrowErrorMatchingInlineSnapshot(` -"types that failed validation: -- [0]: expected value to equal [modern] -- [1]: expected value to equal [legacy]" -`); - }); - }); }); diff --git a/src/core/server/ui_settings/settings/navigation.ts b/src/core/server/ui_settings/settings/navigation.ts index 38064db9e9388..937af4bb9aad1 100644 --- a/src/core/server/ui_settings/settings/navigation.ts +++ b/src/core/server/ui_settings/settings/navigation.ts @@ -37,25 +37,5 @@ export const getNavigationSettings = (): Record => { 'The route must be a relative URL.', }), }, - pageNavigation: { - name: i18n.translate('core.ui_settings.params.pageNavigationName', { - defaultMessage: 'Side nav style', - }), - value: 'modern', - description: i18n.translate('core.ui_settings.params.pageNavigationDesc', { - defaultMessage: 'Change the style of navigation', - }), - type: 'select', - options: ['modern', 'legacy'], - optionLabels: { - modern: i18n.translate('core.ui_settings.params.pageNavigationModern', { - defaultMessage: 'Modern', - }), - legacy: i18n.translate('core.ui_settings.params.pageNavigationLegacy', { - defaultMessage: 'Legacy', - }), - }, - schema: schema.oneOf([schema.literal('modern'), schema.literal('legacy')]), - }, }; }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index d75b2981035f4..28eeb461f7a86 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -77,7 +77,6 @@ export const stackManagementSchema: MakeSchemaFrom = { 'sort:options': { type: 'keyword' }, 'savedObjects:listingLimit': { type: 'long' }, 'query:queryString:options': { type: 'keyword' }, - pageNavigation: { type: 'keyword' }, 'metrics:max_buckets': { type: 'long' }, 'query:allowLeadingWildcards': { type: 'boolean' }, metaFields: { type: 'keyword' }, // it's an array diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 27d9b5ce83203..7bac6a809eca3 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -4268,9 +4268,6 @@ "query:queryString:options": { "type": "keyword" }, - "pageNavigation": { - "type": "keyword" - }, "metrics:max_buckets": { "type": "long" }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9d8951b03f39a..93267c950c10e 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -529,10 +529,6 @@ "core.ui_settings.params.notifications.infoLifetimeTitle": "情報通知時間", "core.ui_settings.params.notifications.warningLifetimeText": "警告通知が画面に表示される時間(ミリ秒単位)です。{infinityValue}に設定すると、無効になります。", "core.ui_settings.params.notifications.warningLifetimeTitle": "警告通知時間", - "core.ui_settings.params.pageNavigationDesc": "ナビゲーションのスタイルを変更", - "core.ui_settings.params.pageNavigationLegacy": "レガシー", - "core.ui_settings.params.pageNavigationModern": "モダン", - "core.ui_settings.params.pageNavigationName": "サイドナビゲーションスタイル", "core.ui_settings.params.storeUrlText": "URLが長くなりすぎるためブラウザーが対応できない場合があります。セッションストレージにURLの一部を保存することでこの問題に対処できるかどうかをテストしています。結果を教えてください!", "core.ui_settings.params.storeUrlTitle": "セッションストレージにURLを格納", "core.ui_settings.params.themeVersionText": "現在のバージョンと次のバージョンのKibanaで使用されるテーマを切り替えます。この設定を適用するにはページの更新が必要です。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index afa8c6d4be51a..41bdf97333dd7 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -529,10 +529,6 @@ "core.ui_settings.params.notifications.infoLifetimeTitle": "信息通知生存时间", "core.ui_settings.params.notifications.warningLifetimeText": "在屏幕上显示警告通知的时间(毫秒)。设置为 {infinityValue} 将禁用此项。", "core.ui_settings.params.notifications.warningLifetimeTitle": "警告通知生存时间", - "core.ui_settings.params.pageNavigationDesc": "更改导航样式", - "core.ui_settings.params.pageNavigationLegacy": "旧版", - "core.ui_settings.params.pageNavigationModern": "现代", - "core.ui_settings.params.pageNavigationName": "侧边导航样式", "core.ui_settings.params.storeUrlText": "有时,URL 可能会变得过长,使某些浏览器无法进行处理。为此,我们将正测试在会话存储中存储 URL 的组成部分是否会有所帮助。请向我们反馈您的体验!", "core.ui_settings.params.storeUrlTitle": "将 URL 存储在会话存储中", "core.ui_settings.params.themeVersionText": "在用于当前版和下一版 Kibana 的主题之间切换。需要刷新页面,才能应用设置。", From de44af3eebfacbb91af3ddd2d8f79959069cad72 Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Tue, 26 Jan 2021 13:08:03 +0200 Subject: [PATCH 08/21] Improve extend search session UI (#89126) * Fix extend search session UI * code review --- x-pack/plugins/data_enhanced/public/plugin.ts | 4 +-- .../sessions_mgmt/application/index.tsx | 4 +-- .../components/actions/extend_button.tsx | 14 +++++++-- .../components/actions/get_action.tsx | 13 +++++++-- .../sessions_mgmt/components/main.test.tsx | 17 ++++++----- .../search/sessions_mgmt/components/main.tsx | 4 +-- .../components/table/table.test.tsx | 29 ++++++++++++------- .../sessions_mgmt/components/table/table.tsx | 11 +++---- .../public/search/sessions_mgmt/index.ts | 6 ++-- .../search/sessions_mgmt/lib/api.test.ts | 24 +++++++++------ .../public/search/sessions_mgmt/lib/api.ts | 21 +++++++++----- .../sessions_mgmt/lib/get_columns.test.tsx | 17 ++++++----- .../search/sessions_mgmt/lib/get_columns.tsx | 4 +-- .../lib/get_expiration_status.ts | 6 ++-- .../server/search/session/monitoring_task.ts | 2 +- 15 files changed, 110 insertions(+), 66 deletions(-) diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index add7a966fee34..edcdea3997c8e 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -66,8 +66,8 @@ export class DataEnhancedPlugin this.config = this.initializerContext.config.get(); if (this.config.search.sessions.enabled) { - const { management: sessionsMgmtConfig } = this.config.search.sessions; - registerSearchSessionsMgmt(core, sessionsMgmtConfig, { management }); + const sessionsConfig = this.config.search.sessions; + registerSearchSessionsMgmt(core, sessionsConfig, { management }); } } diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/application/index.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/application/index.tsx index 27f1482a4d20d..7347f070e91c3 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/application/index.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/application/index.tsx @@ -10,7 +10,7 @@ import type { AppDependencies, IManagementSectionsPluginsSetup, IManagementSectionsPluginsStart, - SessionsMgmtConfigSchema, + SessionsConfigSchema, } from '../'; import { APP } from '../'; import { SearchSessionsMgmtAPI } from '../lib/api'; @@ -20,7 +20,7 @@ import { renderApp } from './render'; export class SearchSessionsMgmtApp { constructor( private coreSetup: CoreSetup, - private config: SessionsMgmtConfigSchema, + private config: SessionsConfigSchema, private params: ManagementAppMountParams, private pluginsSetup: IManagementSectionsPluginsSetup ) {} diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/actions/extend_button.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/actions/extend_button.tsx index 4c8a7b0217688..d9c2bdabcbac1 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/actions/extend_button.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/actions/extend_button.tsx @@ -8,6 +8,8 @@ import { EuiConfirmModal, EuiOverlayMask } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { useState } from 'react'; +import { Duration } from 'moment'; +import moment from 'moment'; import { SearchSessionsMgmtAPI } from '../../lib/api'; import { TableText } from '../'; import { OnActionComplete } from './types'; @@ -15,6 +17,8 @@ import { OnActionComplete } from './types'; interface ExtendButtonProps { id: string; name: string; + expires: string | null; + extendBy: Duration; api: SearchSessionsMgmtAPI; onActionComplete: OnActionComplete; } @@ -23,8 +27,11 @@ const ExtendConfirm = ({ onConfirmDismiss, ...props }: ExtendButtonProps & { onConfirmDismiss: () => void }) => { - const { id, name, api, onActionComplete } = props; + const { id, name, expires, api, extendBy, onActionComplete } = props; const [isLoading, setIsLoading] = useState(false); + const extendByDuration = moment.duration(extendBy); + + const newExpiration = moment(expires).add(extendByDuration); const title = i18n.translate('xpack.data.mgmt.searchSessions.extendModal.title', { defaultMessage: 'Extend search session expiration', @@ -36,9 +43,10 @@ const ExtendConfirm = ({ defaultMessage: 'Cancel', }); const message = i18n.translate('xpack.data.mgmt.searchSessions.extendModal.extendMessage', { - defaultMessage: "When would you like the search session '{name}' to expire?", + defaultMessage: "The search session '{name}' expiration would be extended until {newExpires}.", values: { name, + newExpires: newExpiration.toLocaleString(), }, }); @@ -49,7 +57,7 @@ const ExtendConfirm = ({ onCancel={onConfirmDismiss} onConfirm={async () => { setIsLoading(true); - await api.sendExtend(id, '1'); + await api.sendExtend(id, `${extendByDuration.asMilliseconds()}ms`); onActionComplete(); }} confirmButtonText={confirm} diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/actions/get_action.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/actions/get_action.tsx index 5bf0fbda5b5cc..c80cf6c244895 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/actions/get_action.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/actions/get_action.tsx @@ -17,7 +17,7 @@ import { ACTION, OnActionComplete } from './types'; export const getAction = ( api: SearchSessionsMgmtAPI, actionType: string, - { id, name, reloadUrl }: UISession, + { id, name, expires, reloadUrl }: UISession, onActionComplete: OnActionComplete ): IClickActionDescriptor | null => { switch (actionType) { @@ -39,7 +39,16 @@ export const getAction = ( return { iconType: extendSessionIcon, textColor: 'default', - label: , + label: ( + + ), }; default: diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/main.test.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/main.test.tsx index e01d1a28c5e54..14aea4bcbf59b 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/main.test.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/main.test.tsx @@ -12,7 +12,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; import { coreMock } from 'src/core/public/mocks'; import { SessionsClient } from 'src/plugins/data/public/search'; -import { SessionsMgmtConfigSchema } from '..'; +import { SessionsConfigSchema } from '..'; import { SearchSessionsMgmtAPI } from '../lib/api'; import { AsyncSearchIntroDocumentation } from '../lib/documentation'; import { LocaleWrapper, mockUrls } from '../__mocks__'; @@ -20,7 +20,7 @@ import { SearchSessionsMgmtMain } from './main'; let mockCoreSetup: MockedKeys; let mockCoreStart: MockedKeys; -let mockConfig: SessionsMgmtConfigSchema; +let mockConfig: SessionsConfigSchema; let sessionsClient: SessionsClient; let api: SearchSessionsMgmtAPI; @@ -29,11 +29,14 @@ describe('Background Search Session Management Main', () => { mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); mockConfig = { - expiresSoonWarning: moment.duration(1, 'days'), - maxSessions: 2000, - refreshInterval: moment.duration(1, 'seconds'), - refreshTimeout: moment.duration(10, 'minutes'), - }; + defaultExpiration: moment.duration('7d'), + management: { + expiresSoonWarning: moment.duration(1, 'days'), + maxSessions: 2000, + refreshInterval: moment.duration(1, 'seconds'), + refreshTimeout: moment.duration(10, 'minutes'), + }, + } as any; sessionsClient = new SessionsClient({ http: mockCoreSetup.http }); diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/main.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/main.tsx index 80c6a580dd183..cdf92d69f6438 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/main.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/main.tsx @@ -17,7 +17,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import type { CoreStart, HttpStart } from 'kibana/public'; import React from 'react'; -import type { SessionsMgmtConfigSchema } from '../'; +import type { SessionsConfigSchema } from '../'; import type { SearchSessionsMgmtAPI } from '../lib/api'; import type { AsyncSearchIntroDocumentation } from '../lib/documentation'; import { TableText } from './'; @@ -29,7 +29,7 @@ interface Props { api: SearchSessionsMgmtAPI; http: HttpStart; timezone: string; - config: SessionsMgmtConfigSchema; + config: SessionsConfigSchema; } export function SearchSessionsMgmtMain({ documentation, ...tableProps }: Props) { diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.test.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.test.tsx index 51cec8f2afeff..a99fc26889a24 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.test.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.test.tsx @@ -13,14 +13,14 @@ import React from 'react'; import { coreMock } from 'src/core/public/mocks'; import { SessionsClient } from 'src/plugins/data/public/search'; import { SearchSessionStatus } from '../../../../../common/search'; -import { SessionsMgmtConfigSchema } from '../../'; +import { SessionsConfigSchema } from '../../'; import { SearchSessionsMgmtAPI } from '../../lib/api'; import { LocaleWrapper, mockUrls } from '../../__mocks__'; import { SearchSessionsMgmtTable } from './table'; let mockCoreSetup: MockedKeys; let mockCoreStart: CoreStart; -let mockConfig: SessionsMgmtConfigSchema; +let mockConfig: SessionsConfigSchema; let sessionsClient: SessionsClient; let api: SearchSessionsMgmtAPI; @@ -29,11 +29,14 @@ describe('Background Search Session Management Table', () => { mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); mockConfig = { - expiresSoonWarning: moment.duration(1, 'days'), - maxSessions: 2000, - refreshInterval: moment.duration(1, 'seconds'), - refreshTimeout: moment.duration(10, 'minutes'), - }; + defaultExpiration: moment.duration('7d'), + management: { + expiresSoonWarning: moment.duration(1, 'days'), + maxSessions: 2000, + refreshInterval: moment.duration(1, 'seconds'), + refreshTimeout: moment.duration(10, 'minutes'), + }, + } as any; sessionsClient = new SessionsClient({ http: mockCoreSetup.http }); api = new SearchSessionsMgmtAPI(sessionsClient, mockConfig, { @@ -134,7 +137,10 @@ describe('Background Search Session Management Table', () => { sessionsClient.find = jest.fn(); mockConfig = { ...mockConfig, - refreshInterval: moment.duration(10, 'seconds'), + management: { + ...mockConfig.management, + refreshInterval: moment.duration(10, 'seconds'), + }, }; await act(async () => { @@ -162,8 +168,11 @@ describe('Background Search Session Management Table', () => { mockConfig = { ...mockConfig, - refreshInterval: moment.duration(1, 'day'), - refreshTimeout: moment.duration(2, 'days'), + management: { + ...mockConfig.management, + refreshInterval: moment.duration(1, 'day'), + refreshTimeout: moment.duration(2, 'days'), + }, }; await act(async () => { diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.tsx index f7aecdbd58a23..290fa4d74dfeb 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.tsx @@ -12,7 +12,7 @@ import React, { useCallback, useMemo, useRef, useEffect, useState } from 'react' import useDebounce from 'react-use/lib/useDebounce'; import useInterval from 'react-use/lib/useInterval'; import { TableText } from '../'; -import { SessionsMgmtConfigSchema } from '../..'; +import { SessionsConfigSchema } from '../..'; import { SearchSessionsMgmtAPI } from '../../lib/api'; import { getColumns } from '../../lib/get_columns'; import { UISession } from '../../types'; @@ -26,7 +26,7 @@ interface Props { core: CoreStart; api: SearchSessionsMgmtAPI; timezone: string; - config: SessionsMgmtConfigSchema; + config: SessionsConfigSchema; } export function SearchSessionsMgmtTable({ core, api, timezone, config, ...props }: Props) { @@ -35,9 +35,10 @@ export function SearchSessionsMgmtTable({ core, api, timezone, config, ...props const [debouncedIsLoading, setDebouncedIsLoading] = useState(false); const [pagination, setPagination] = useState({ pageIndex: 0 }); const showLatestResultsHandler = useRef(); - const refreshInterval = useMemo(() => moment.duration(config.refreshInterval).asMilliseconds(), [ - config.refreshInterval, - ]); + const refreshInterval = useMemo( + () => moment.duration(config.management.refreshInterval).asMilliseconds(), + [config.management.refreshInterval] + ); // Debounce rendering the state of the Refresh button useDebounce( diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/index.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/index.ts index 76a5d440cd898..695252462794b 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/index.ts +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/index.ts @@ -33,7 +33,7 @@ export interface AppDependencies { api: SearchSessionsMgmtAPI; http: HttpStart; i18n: I18nStart; - config: SessionsMgmtConfigSchema; + config: SessionsConfigSchema; } export const APP = { @@ -44,11 +44,11 @@ export const APP = { }), }; -export type SessionsMgmtConfigSchema = ConfigSchema['search']['sessions']['management']; +export type SessionsConfigSchema = ConfigSchema['search']['sessions']; export function registerSearchSessionsMgmt( coreSetup: CoreSetup, - config: SessionsMgmtConfigSchema, + config: SessionsConfigSchema, services: IManagementSectionsPluginsSetup ) { services.management.sections.section.kibana.registerApp({ diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.test.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.test.ts index 5b337dfd03eb1..068225d0df8c3 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.test.ts +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.test.ts @@ -11,14 +11,14 @@ import { coreMock } from 'src/core/public/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import type { SavedObjectsFindResponse } from 'src/core/server'; import { SessionsClient } from 'src/plugins/data/public/search'; -import type { SessionsMgmtConfigSchema } from '../'; +import type { SessionsConfigSchema } from '../'; import { SearchSessionStatus } from '../../../../common/search'; import { mockUrls } from '../__mocks__'; import { SearchSessionsMgmtAPI } from './api'; let mockCoreSetup: MockedKeys; let mockCoreStart: MockedKeys; -let mockConfig: SessionsMgmtConfigSchema; +let mockConfig: SessionsConfigSchema; let sessionsClient: SessionsClient; describe('Search Sessions Management API', () => { @@ -26,11 +26,14 @@ describe('Search Sessions Management API', () => { mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); mockConfig = { - expiresSoonWarning: moment.duration('1d'), - maxSessions: 2000, - refreshInterval: moment.duration('1s'), - refreshTimeout: moment.duration('10m'), - }; + defaultExpiration: moment.duration('7d'), + management: { + expiresSoonWarning: moment.duration(1, 'days'), + maxSessions: 2000, + refreshInterval: moment.duration(1, 'seconds'), + refreshTimeout: moment.duration(10, 'minutes'), + }, + } as any; sessionsClient = new SessionsClient({ http: mockCoreSetup.http }); }); @@ -93,8 +96,11 @@ describe('Search Sessions Management API', () => { test('handle timeout error', async () => { mockConfig = { ...mockConfig, - refreshInterval: moment.duration(1, 'hours'), - refreshTimeout: moment.duration(1, 'seconds'), + management: { + ...mockConfig.management, + refreshInterval: moment.duration(1, 'hours'), + refreshTimeout: moment.duration(1, 'seconds'), + }, }; sessionsClient.find = jest.fn().mockImplementation(async () => { diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.ts index a2bd6b1a549be..c6a3d088b3cda 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.ts +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.ts @@ -10,7 +10,7 @@ import moment from 'moment'; import { from, race, timer } from 'rxjs'; import { mapTo, tap } from 'rxjs/operators'; import type { SharePluginStart } from 'src/plugins/share/public'; -import { SessionsMgmtConfigSchema } from '../'; +import { SessionsConfigSchema } from '../'; import type { ISessionsClient } from '../../../../../../../src/plugins/data/public'; import type { SearchSessionSavedObjectAttributes } from '../../../../common'; import { SearchSessionStatus } from '../../../../common/search'; @@ -47,10 +47,9 @@ async function getUrlFromState( } // Helper: factory for a function to map server objects to UI objects -const mapToUISession = ( - urls: UrlGeneratorsStart, - { expiresSoonWarning }: SessionsMgmtConfigSchema -) => async (savedObject: SavedObject): Promise => { +const mapToUISession = (urls: UrlGeneratorsStart, config: SessionsConfigSchema) => async ( + savedObject: SavedObject +): Promise => { const { name, appId, @@ -92,7 +91,7 @@ interface SearcgSessuibManagementDeps { export class SearchSessionsMgmtAPI { constructor( private sessionsClient: ISessionsClient, - private config: SessionsMgmtConfigSchema, + private config: SessionsConfigSchema, private deps: SearcgSessuibManagementDeps ) {} @@ -101,12 +100,14 @@ export class SearchSessionsMgmtAPI { saved_objects: object[]; } - const refreshTimeout = moment.duration(this.config.refreshTimeout); + const mgmtConfig = this.config.management; + + const refreshTimeout = moment.duration(mgmtConfig.refreshTimeout); const fetch$ = from( this.sessionsClient.find({ page: 1, - perPage: this.config.maxSessions, + perPage: mgmtConfig.maxSessions, sortField: 'created', sortOrder: 'asc', }) @@ -149,6 +150,10 @@ export class SearchSessionsMgmtAPI { this.deps.application.navigateToUrl(reloadUrl); } + public getExtendByDuration() { + return this.config.defaultExpiration; + } + // Cancel and expire public async sendCancel(id: string): Promise { try { diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.test.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.test.tsx index ce441efea7385..ec4f2f63ceed1 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.test.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.test.tsx @@ -12,7 +12,7 @@ import moment from 'moment'; import { ReactElement } from 'react'; import { coreMock } from 'src/core/public/mocks'; import { SessionsClient } from 'src/plugins/data/public/search'; -import { SessionsMgmtConfigSchema } from '../'; +import { SessionsConfigSchema } from '../'; import { SearchSessionStatus } from '../../../../common/search'; import { OnActionComplete } from '../components'; import { UISession } from '../types'; @@ -22,7 +22,7 @@ import { getColumns } from './get_columns'; let mockCoreSetup: MockedKeys; let mockCoreStart: CoreStart; -let mockConfig: SessionsMgmtConfigSchema; +let mockConfig: SessionsConfigSchema; let api: SearchSessionsMgmtAPI; let sessionsClient: SessionsClient; let handleAction: OnActionComplete; @@ -35,11 +35,14 @@ describe('Search Sessions Management table column factory', () => { mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); mockConfig = { - expiresSoonWarning: moment.duration(1, 'days'), - maxSessions: 2000, - refreshInterval: moment.duration(1, 'seconds'), - refreshTimeout: moment.duration(10, 'minutes'), - }; + defaultExpiration: moment.duration('7d'), + management: { + expiresSoonWarning: moment.duration(1, 'days'), + maxSessions: 2000, + refreshInterval: moment.duration(1, 'seconds'), + refreshTimeout: moment.duration(10, 'minutes'), + }, + } as any; sessionsClient = new SessionsClient({ http: mockCoreSetup.http }); api = new SearchSessionsMgmtAPI(sessionsClient, mockConfig, { diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.tsx index 090336c37a98f..1ced354a28039 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.tsx +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.tsx @@ -20,7 +20,7 @@ import { capitalize } from 'lodash'; import React from 'react'; import { FormattedMessage } from 'react-intl'; import { RedirectAppLinks } from '../../../../../../../src/plugins/kibana_react/public'; -import { SessionsMgmtConfigSchema } from '../'; +import { SessionsConfigSchema } from '../'; import { SearchSessionStatus } from '../../../../common/search'; import { TableText } from '../components'; import { OnActionComplete, PopoverActionsMenu } from '../components'; @@ -45,7 +45,7 @@ function isSessionRestorable(status: SearchSessionStatus) { export const getColumns = ( core: CoreStart, api: SearchSessionsMgmtAPI, - config: SessionsMgmtConfigSchema, + config: SessionsConfigSchema, timezone: string, onActionComplete: OnActionComplete ): Array> => { diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_expiration_status.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_expiration_status.ts index 3c167d6dbe41a..5a52fce760d78 100644 --- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_expiration_status.ts +++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_expiration_status.ts @@ -6,9 +6,9 @@ import { i18n } from '@kbn/i18n'; import moment from 'moment'; -import { SessionsMgmtConfigSchema } from '../'; +import { SessionsConfigSchema } from '../'; -export const getExpirationStatus = (config: SessionsMgmtConfigSchema, expires: string | null) => { +export const getExpirationStatus = (config: SessionsConfigSchema, expires: string | null) => { const tNow = moment.utc().valueOf(); const tFuture = moment.utc(expires).valueOf(); @@ -16,7 +16,7 @@ export const getExpirationStatus = (config: SessionsMgmtConfigSchema, expires: s // and the session was early expired when the browser refreshed the listing const durationToExpire = moment.duration(tFuture - tNow); const expiresInDays = Math.floor(durationToExpire.asDays()); - const sufficientDays = Math.ceil(moment.duration(config.expiresSoonWarning).asDays()); + const sufficientDays = Math.ceil(moment.duration(config.management.expiresSoonWarning).asDays()); let toolTipContent = i18n.translate('xpack.data.mgmt.searchSessions.status.expiresSoonInDays', { defaultMessage: 'Expires in {numDays} days', diff --git a/x-pack/plugins/data_enhanced/server/search/session/monitoring_task.ts b/x-pack/plugins/data_enhanced/server/search/session/monitoring_task.ts index d32dcf72a4205..332e69b119bb6 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/monitoring_task.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/monitoring_task.ts @@ -76,7 +76,7 @@ export async function scheduleSearchSessionsTasks( params: {}, }); - logger.debug(`Background search task, scheduled to run`); + logger.debug(`Search sessions task, scheduled to run`); } catch (e) { logger.debug(`Error scheduling task, received ${e.message}`); } From 88f76b5995889d6a0c28c8a34c20c740d5ae0002 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 26 Jan 2021 12:26:11 +0100 Subject: [PATCH 09/21] Reduce index management plugin page load bundle size (#88656) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../helpers/setup_environment.tsx | 2 +- .../__jest__/components/index_table.test.js | 2 +- .../common/constants/index.ts | 1 - .../plugins/index_management/common/index.ts | 2 +- .../application/mount_management_section.ts | 41 +++++++++++++++---- .../store/selectors/extension_service.ts | 19 +++++++++ .../application/store/selectors/index.js | 10 +---- .../store/selectors/indices_filter.test.ts | 3 +- .../plugins/index_management/public/index.ts | 2 +- .../plugins/index_management/public/plugin.ts | 35 ++++++---------- .../plugins/index_management/server/plugin.ts | 2 +- 11 files changed, 72 insertions(+), 47 deletions(-) create mode 100644 x-pack/plugins/index_management/public/application/store/selectors/extension_service.ts diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx index 87e16b0d7bfe0..afafdb2c6cda6 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/setup_environment.tsx @@ -23,7 +23,7 @@ import { notificationService } from '../../../public/application/services/notifi import { ExtensionsService } from '../../../public/services'; import { UiMetricService } from '../../../public/application/services/ui_metric'; import { setUiMetricService } from '../../../public/application/services/api'; -import { setExtensionsService } from '../../../public/application/store/selectors'; +import { setExtensionsService } from '../../../public/application/store/selectors/extension_service'; import { MappingsEditorProvider, ComponentTemplatesProvider, diff --git a/x-pack/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/plugins/index_management/__jest__/components/index_table.test.js index b2526d6b4db5e..2649986c4229e 100644 --- a/x-pack/plugins/index_management/__jest__/components/index_table.test.js +++ b/x-pack/plugins/index_management/__jest__/components/index_table.test.js @@ -27,7 +27,7 @@ import { notificationService } from '../../public/application/services/notificat import { httpService } from '../../public/application/services/http'; import { setUiMetricService } from '../../public/application/services/api'; import { indexManagementStore } from '../../public/application/store'; -import { setExtensionsService } from '../../public/application/store/selectors'; +import { setExtensionsService } from '../../public/application/store/selectors/extension_service'; import { BASE_PATH, API_BASE_PATH } from '../../common/constants'; import { ExtensionsService } from '../../public/services'; import sinon from 'sinon'; diff --git a/x-pack/plugins/index_management/common/constants/index.ts b/x-pack/plugins/index_management/common/constants/index.ts index 11240271503e2..5adb9f6098348 100644 --- a/x-pack/plugins/index_management/common/constants/index.ts +++ b/x-pack/plugins/index_management/common/constants/index.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -export { PLUGIN } from './plugin'; export { BASE_PATH } from './base_path'; export { API_BASE_PATH } from './api_base_path'; export { INVALID_INDEX_PATTERN_CHARS, INVALID_TEMPLATE_NAME_CHARS } from './invalid_characters'; diff --git a/x-pack/plugins/index_management/common/index.ts b/x-pack/plugins/index_management/common/index.ts index 119d4e0c54edd..ea5ee5ee8e001 100644 --- a/x-pack/plugins/index_management/common/index.ts +++ b/x-pack/plugins/index_management/common/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export { PLUGIN, API_BASE_PATH, BASE_PATH } from './constants'; +export { API_BASE_PATH, BASE_PATH } from './constants'; export { getTemplateParameter } from './lib'; diff --git a/x-pack/plugins/index_management/public/application/mount_management_section.ts b/x-pack/plugins/index_management/public/application/mount_management_section.ts index ff7fc03ef7ae6..b94718c14d3aa 100644 --- a/x-pack/plugins/index_management/public/application/mount_management_section.ts +++ b/x-pack/plugins/index_management/public/application/mount_management_section.ts @@ -10,28 +10,46 @@ import { ManagementAppMountParams } from 'src/plugins/management/public/'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/public'; import { FleetSetup } from '../../../fleet/public'; -import { PLUGIN } from '../../common/constants'; +import { UIM_APP_NAME } from '../../common/constants'; +import { PLUGIN } from '../../common/constants/plugin'; import { ExtensionsService } from '../services'; import { StartDependencies } from '../types'; import { AppDependencies } from './app_context'; import { breadcrumbService } from './services/breadcrumbs'; import { documentationService } from './services/documentation'; -import { HttpService, NotificationService, UiMetricService } from './services'; +import { UiMetricService } from './services'; import { renderApp } from '.'; +import { setUiMetricService } from './services/api'; +import { notificationService } from './services/notification'; +import { httpService } from './services/http'; -interface InternalServices { - httpService: HttpService; - notificationService: NotificationService; - uiMetricService: UiMetricService; - extensionsService: ExtensionsService; +function initSetup({ + usageCollection, + coreSetup, +}: { + coreSetup: CoreSetup; + usageCollection: UsageCollectionSetup; +}) { + const { http, notifications } = coreSetup; + + httpService.setup(http); + notificationService.setup(notifications); + + const uiMetricService = new UiMetricService(UIM_APP_NAME); + + setUiMetricService(uiMetricService); + + uiMetricService.setup(usageCollection); + + return { uiMetricService }; } export async function mountManagementSection( coreSetup: CoreSetup, usageCollection: UsageCollectionSetup, - services: InternalServices, params: ManagementAppMountParams, + extensionsService: ExtensionsService, fleet?: FleetSetup ) { const { element, setBreadcrumbs, history } = params; @@ -50,6 +68,11 @@ export async function mountManagementSection( breadcrumbService.setup(setBreadcrumbs); documentationService.setup(docLinks); + const { uiMetricService } = initSetup({ + usageCollection, + coreSetup, + }); + const appDependencies: AppDependencies = { core: { fatalErrors, @@ -59,7 +82,7 @@ export async function mountManagementSection( usageCollection, fleet, }, - services, + services: { httpService, notificationService, uiMetricService, extensionsService }, history, setBreadcrumbs, uiSettings, diff --git a/x-pack/plugins/index_management/public/application/store/selectors/extension_service.ts b/x-pack/plugins/index_management/public/application/store/selectors/extension_service.ts new file mode 100644 index 0000000000000..c5ce1c359b99b --- /dev/null +++ b/x-pack/plugins/index_management/public/application/store/selectors/extension_service.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ExtensionsService } from '../../../services'; + +// Temporary hack to provide the extensionsService instance to this file. +// TODO: Refactor and export all the app selectors through the app dependencies context + +let extensionsService; +export const setExtensionsService = (_extensionsService: ExtensionsService) => { + extensionsService = _extensionsService; +}; + +export { extensionsService }; + +// End hack diff --git a/x-pack/plugins/index_management/public/application/store/selectors/index.js b/x-pack/plugins/index_management/public/application/store/selectors/index.js index c80658581dbee..800cf1473d1a7 100644 --- a/x-pack/plugins/index_management/public/application/store/selectors/index.js +++ b/x-pack/plugins/index_management/public/application/store/selectors/index.js @@ -9,15 +9,9 @@ import { createSelector } from 'reselect'; import * as qs from 'query-string'; import { indexStatusLabels } from '../../lib/index_status_labels'; import { sortTable } from '../../services'; +import { extensionsService } from './extension_service'; -// Temporary hack to provide the extensionsService instance to this file. -// TODO: Refactor and export all the app selectors through the app dependencies context - -let extensionsService; -export const setExtensionsService = (_extensionsService) => { - extensionsService = _extensionsService; -}; -// End hack +export { extensionsService }; export const getDetailPanelData = (state) => state.detailPanel.data; export const getDetailPanelError = (state) => state.detailPanel.error; diff --git a/x-pack/plugins/index_management/public/application/store/selectors/indices_filter.test.ts b/x-pack/plugins/index_management/public/application/store/selectors/indices_filter.test.ts index f230ddd18e9eb..ca63f305b8c60 100644 --- a/x-pack/plugins/index_management/public/application/store/selectors/indices_filter.test.ts +++ b/x-pack/plugins/index_management/public/application/store/selectors/indices_filter.test.ts @@ -4,9 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ import { ExtensionsService } from '../../../services'; -import { getFilteredIndices, setExtensionsService } from '.'; +import { getFilteredIndices } from '.'; // @ts-ignore import { defaultTableState } from '../reducers/table_state'; +import { setExtensionsService } from './extension_service'; describe('getFilteredIndices selector', () => { let extensionService: ExtensionsService; diff --git a/x-pack/plugins/index_management/public/index.ts b/x-pack/plugins/index_management/public/index.ts index da6d90f22a384..d40d16ad4f74a 100644 --- a/x-pack/plugins/index_management/public/index.ts +++ b/x-pack/plugins/index_management/public/index.ts @@ -15,4 +15,4 @@ export { IndexManagementPluginSetup } from './types'; export { getIndexListUri } from './application/services/routing'; -export { Index } from '../common'; +export type { Index } from '../common'; diff --git a/x-pack/plugins/index_management/public/plugin.ts b/x-pack/plugins/index_management/public/plugin.ts index 9eeeaa9d3c723..35413bd4f9ca1 100644 --- a/x-pack/plugins/index_management/public/plugin.ts +++ b/x-pack/plugins/index_management/public/plugin.ts @@ -6,54 +6,43 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup } from '../../../../src/core/public'; +import { setExtensionsService } from './application/store/selectors/extension_service'; -import { UIM_APP_NAME, PLUGIN } from '../common/constants'; - -import { httpService } from './application/services/http'; -import { notificationService } from './application/services/notification'; -import { UiMetricService } from './application/services/ui_metric'; - -import { setExtensionsService } from './application/store/selectors'; -import { setUiMetricService } from './application/services/api'; +import { ExtensionsService } from './services'; import { IndexManagementPluginSetup, SetupDependencies, StartDependencies } from './types'; -import { ExtensionsService } from './services'; + +// avoid import from index files in plugin.ts, use specific import paths +import { PLUGIN } from '../common/constants/plugin'; export class IndexMgmtUIPlugin { - private uiMetricService = new UiMetricService(UIM_APP_NAME); private extensionsService = new ExtensionsService(); constructor() { // Temporary hack to provide the service instances in module files in order to avoid a big refactor // For the selectors we should expose them through app dependencies and read them from there on each container component. setExtensionsService(this.extensionsService); - setUiMetricService(this.uiMetricService); } public setup( coreSetup: CoreSetup, plugins: SetupDependencies ): IndexManagementPluginSetup { - const { http, notifications } = coreSetup; const { fleet, usageCollection, management } = plugins; - httpService.setup(http); - notificationService.setup(notifications); - this.uiMetricService.setup(usageCollection); - management.sections.section.data.registerApp({ id: PLUGIN.id, title: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }), order: 0, mount: async (params) => { const { mountManagementSection } = await import('./application/mount_management_section'); - const services = { - httpService, - notificationService, - uiMetricService: this.uiMetricService, - extensionsService: this.extensionsService, - }; - return mountManagementSection(coreSetup, usageCollection, services, params, fleet); + return mountManagementSection( + coreSetup, + usageCollection, + params, + this.extensionsService, + fleet + ); }, }); diff --git a/x-pack/plugins/index_management/server/plugin.ts b/x-pack/plugins/index_management/server/plugin.ts index 3717e7e94d29f..aaa11bc2d47cc 100644 --- a/x-pack/plugins/index_management/server/plugin.ts +++ b/x-pack/plugins/index_management/server/plugin.ts @@ -13,7 +13,7 @@ import { ILegacyCustomClusterClient, } from 'src/core/server'; -import { PLUGIN } from '../common'; +import { PLUGIN } from '../common/constants/plugin'; import { Dependencies } from './types'; import { ApiRoutes } from './routes'; import { License, IndexDataEnricher } from './services'; From c74a2b25a6a740470d8f0c5d8513296d2d55d9d7 Mon Sep 17 00:00:00 2001 From: Dhruv Bodani Date: Tue, 26 Jan 2021 18:11:24 +0530 Subject: [PATCH 10/21] add a "Refresh" button to the alerts list and alert details views (#87016) * add refresh button to alerts list * add refresh button to Alerts Details Page * fix: add EuiFlexItem tag * add tests for refresh button in alerts_list and alert_details * fix: add test for requestRefresh and loadAlerts Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/alert_details.test.tsx | 36 +++++++++++++++++++ .../components/alert_details.tsx | 14 ++++++++ .../components/alerts_list.test.tsx | 7 ++++ .../alerts_list/components/alerts_list.tsx | 12 +++++++ 4 files changed, 69 insertions(+) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx index 13f1aea91c7ac..731152f4a9d63 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.test.tsx @@ -796,6 +796,42 @@ describe('edit button', () => { }); }); +describe('refresh button', () => { + it('should call requestRefresh when clicked', () => { + const alert = mockAlert(); + const alertType: AlertType = { + id: '.noop', + name: 'No Op', + actionGroups: [{ id: 'default', name: 'Default' }], + recoveryActionGroup, + actionVariables: { context: [], state: [], params: [] }, + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + producer: ALERTS_FEATURE_ID, + authorizedConsumers, + enabledInLicense: true, + }; + + const requestRefresh = jest.fn(); + const refreshButton = shallow( + + ) + .find('[data-test-subj="refreshAlertsButton"]') + .first(); + + expect(refreshButton.exists()).toBeTruthy(); + + refreshButton.simulate('click'); + expect(requestRefresh).toHaveBeenCalledTimes(1); + }); +}); + function mockAlert(overloads: Partial = {}): Alert { return { id: uuid.v4(), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx index 5bb8d47988eed..c2a64bfa3a207 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_details.tsx @@ -163,6 +163,20 @@ export const AlertDetails: React.FunctionComponent = ({ ) : null} + + + + + diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx index 875268bd93112..8ca3edb1c68df 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.test.tsx @@ -270,6 +270,13 @@ describe('alerts_list component with items', () => { expect(wrapper.find('[data-test-subj="alertStatus-ok"]').length).toBeGreaterThan(0); expect(wrapper.find('[data-test-subj="alertStatus-pending"]').length).toBeGreaterThan(0); expect(wrapper.find('[data-test-subj="alertStatus-unknown"]').length).toBe(0); + expect(wrapper.find('[data-test-subj="refreshAlertsButton"]').exists()).toBeTruthy(); + }); + + it('loads alerts when refresh button is clicked', async () => { + await setup(); + wrapper.find('[data-test-subj="refreshAlertsButton"]').first().simulate('click'); + expect(loadAlerts).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx index a1a4cfcab18ef..293d471560503 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx @@ -406,6 +406,18 @@ export const AlertsList: React.FunctionComponent = () => { selectedStatuses={alertStatusesFilter} onChange={(ids: string[]) => setAlertStatusesFilter(ids)} />, + + + , ]; const authorizedToModifySelectedAlerts = selectedIds.length From dcba2ab8293546530ea2bb701edc8516c8cfd9fc Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Tue, 26 Jan 2021 14:16:08 +0100 Subject: [PATCH 11/21] Delete dead indices.delete code from v1 migrations (#89059) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../saved_objects/migrations/core/call_cluster.ts | 2 +- .../migrations/core/elastic_index.test.ts | 11 ----------- .../saved_objects/migrations/core/elastic_index.ts | 4 ---- .../migrations/core/migration_es_client.ts | 1 - 4 files changed, 1 insertion(+), 17 deletions(-) diff --git a/src/core/server/saved_objects/migrations/core/call_cluster.ts b/src/core/server/saved_objects/migrations/core/call_cluster.ts index ba6027f711b62..2cb1656833728 100644 --- a/src/core/server/saved_objects/migrations/core/call_cluster.ts +++ b/src/core/server/saved_objects/migrations/core/call_cluster.ts @@ -18,7 +18,7 @@ export interface CallCluster { (path: 'bulk', opts: { body: object[] }): Promise; (path: 'count', opts: CountOpts): Promise<{ count: number; _shards: ShardsInfo }>; (path: 'clearScroll', opts: { scrollId: string }): Promise; - (path: 'indices.create' | 'indices.delete', opts: IndexCreationOpts): Promise; + (path: 'indices.create', opts: IndexCreationOpts): Promise; (path: 'indices.exists', opts: IndexOpts): Promise; (path: 'indices.existsAlias', opts: { name: string }): Promise; (path: 'indices.get', opts: IndexOpts & Ignorable): Promise; diff --git a/src/core/server/saved_objects/migrations/core/elastic_index.test.ts b/src/core/server/saved_objects/migrations/core/elastic_index.test.ts index 32ecea94826ff..4b35b017a7063 100644 --- a/src/core/server/saved_objects/migrations/core/elastic_index.test.ts +++ b/src/core/server/saved_objects/migrations/core/elastic_index.test.ts @@ -107,17 +107,6 @@ describe('ElasticIndex', () => { }); }); - describe('deleteIndex', () => { - test('calls indices.delete', async () => { - await Index.deleteIndex(client, '.lotr'); - - expect(client.indices.delete).toHaveBeenCalledTimes(1); - expect(client.indices.delete).toHaveBeenCalledWith({ - index: '.lotr', - }); - }); - }); - describe('claimAlias', () => { test('handles unaliased indices', async () => { client.indices.getAlias.mockResolvedValue( diff --git a/src/core/server/saved_objects/migrations/core/elastic_index.ts b/src/core/server/saved_objects/migrations/core/elastic_index.ts index 9cdec926a56ba..aa7802320dfb7 100644 --- a/src/core/server/saved_objects/migrations/core/elastic_index.ts +++ b/src/core/server/saved_objects/migrations/core/elastic_index.ts @@ -221,10 +221,6 @@ export async function createIndex( }); } -export async function deleteIndex(client: MigrationEsClient, index: string) { - await client.indices.delete({ index }); -} - /** * Converts an index to an alias. The `alias` parameter is the desired alias name which currently * is a concrete index. This function will reindex `alias` into a new index, delete the `alias` diff --git a/src/core/server/saved_objects/migrations/core/migration_es_client.ts b/src/core/server/saved_objects/migrations/core/migration_es_client.ts index 2653e96e1b8d5..c4bb19d8223ff 100644 --- a/src/core/server/saved_objects/migrations/core/migration_es_client.ts +++ b/src/core/server/saved_objects/migrations/core/migration_es_client.ts @@ -20,7 +20,6 @@ const methods = [ 'clearScroll', 'count', 'indices.create', - 'indices.delete', 'indices.deleteTemplate', 'indices.get', 'indices.getAlias', From 3121e47a2d62f99add4d487da734f3f8f831cd31 Mon Sep 17 00:00:00 2001 From: "Devin W. Hurley" Date: Tue, 26 Jan 2021 08:25:58 -0500 Subject: [PATCH 12/21] [Security Solution] [Detections] Only check privileges if index param is not empty in rule definition (#89147) * only check privileges if index param is not empty * fix jest test i added in previous commit, fixes bug where timestamp field was printed twice in partial failure message * adds two unit tests to check the error messages written from hasTimestampFields util function --- .../signals/__mocks__/es_results.ts | 8 +- .../signals/signal_rule_alert_type.test.ts | 29 ++++++ .../signals/signal_rule_alert_type.ts | 85 +++++++++--------- .../detection_engine/signals/utils.test.ts | 89 +++++++++++++++++++ .../lib/detection_engine/signals/utils.ts | 6 +- 5 files changed, 168 insertions(+), 49 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts index 6718ff2d1f15f..6ff8b61f4120a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts @@ -14,11 +14,7 @@ import { SignalHit, WrappedSignalHit, } from '../types'; -import { - Logger, - SavedObject, - SavedObjectsFindResponse, -} from '../../../../../../../../src/core/server'; +import { SavedObject, SavedObjectsFindResponse } from '../../../../../../../../src/core/server'; import { loggingSystemMock } from '../../../../../../../../src/core/server/mocks'; import { RuleTypeParams } from '../../types'; import { IRuleStatusSOAttributes } from '../../rules/types'; @@ -615,7 +611,7 @@ export const exampleFindRuleStatusResponse: ( saved_objects: mockStatuses.map((obj) => ({ ...obj, score: 1 })), }); -export const mockLogger: Logger = loggingSystemMock.createLogger(); +export const mockLogger = loggingSystemMock.createLogger(); export const sampleBulkErrorItem = ( { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts index f00900255a968..cce781f82e64f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts @@ -538,6 +538,35 @@ describe('rules_notification_alert_type', () => { expect(ruleStatusService.success).toHaveBeenCalled(); }); + it('should not call checkPrivileges if ML rule', async () => { + const ruleAlert = getMlResult(); + payload = getPayload(ruleAlert, alertServices) as jest.Mocked; + jobsSummaryMock.mockResolvedValue([ + { + id: 'some_job_id', + jobState: 'started', + datafeedState: 'started', + }, + ]); + (findMlSignals as jest.Mock).mockResolvedValue({ + _shards: { failed: 0 }, + hits: { + hits: [{}], + }, + }); + (bulkCreateMlSignals as jest.Mock).mockResolvedValue({ + success: true, + bulkCreateDuration: 1, + createdItemsCount: 1, + errors: [], + }); + (checkPrivileges as jest.Mock).mockClear(); + + await alert.executor(payload); + expect(checkPrivileges).toHaveBeenCalledTimes(0); + expect(ruleStatusService.success).toHaveBeenCalled(); + }); + it('should call scheduleActions if signalsCount was greater than 0 and rule has actions defined', async () => { const ruleAlert = getMlResult(); ruleAlert.actions = [ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts index 370f2555b02b8..d08ab66af5683 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts @@ -186,49 +186,52 @@ export const signalRulesAlertType = ({ // move this collection of lines into a function in utils // so that we can use it in create rules route, bulk, etc. try { - const hasTimestampOverride = timestampOverride != null && !isEmpty(timestampOverride); - const [privileges, timestampFieldCaps] = await Promise.all([ - pipe( - { services, version, index }, - ({ services: svc, version: ver, index: idx }) => - pipe( - tryCatch(() => getInputIndex(svc, ver, idx), toError), - chain((indices) => tryCatch(() => checkPrivileges(svc, indices), toError)) - ), - toPromise - ), - services.scopedClusterClient.fieldCaps({ - index, - fields: hasTimestampOverride - ? ['@timestamp', timestampOverride as string] - : ['@timestamp'], - allow_no_indices: false, - include_unmapped: true, - }), - ]); + if (!isEmpty(index)) { + const hasTimestampOverride = timestampOverride != null && !isEmpty(timestampOverride); + const [privileges, timestampFieldCaps] = await Promise.all([ + pipe( + { services, version, index }, + ({ services: svc, version: ver, index: idx }) => + pipe( + tryCatch(() => getInputIndex(svc, ver, idx), toError), + chain((indices) => tryCatch(() => checkPrivileges(svc, indices), toError)) + ), + toPromise + ), + services.scopedClusterClient.fieldCaps({ + index, + fields: hasTimestampOverride + ? ['@timestamp', timestampOverride as string] + : ['@timestamp'], + allow_no_indices: false, + include_unmapped: true, + }), + ]); - wrotePartialFailureStatus = await flow( - () => - tryCatch( - () => hasReadIndexPrivileges(privileges, logger, buildRuleMessage, ruleStatusService), - toError + wrotePartialFailureStatus = await flow( + () => + tryCatch( + () => + hasReadIndexPrivileges(privileges, logger, buildRuleMessage, ruleStatusService), + toError + ), + chain((wroteStatus) => + tryCatch( + () => + hasTimestampFields( + wroteStatus, + hasTimestampOverride ? (timestampOverride as string) : '@timestamp', + timestampFieldCaps, + ruleStatusService, + logger, + buildRuleMessage + ), + toError + ) ), - chain((wroteStatus) => - tryCatch( - () => - hasTimestampFields( - wroteStatus, - hasTimestampOverride ? (timestampOverride as string) : '@timestamp', - timestampFieldCaps, - ruleStatusService, - logger, - buildRuleMessage - ), - toError - ) - ), - toPromise - )(); + toPromise + )(); + } } catch (exc) { logger.error(buildRuleMessage(`Check privileges failed to execute ${exc}`)); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index ac004a7fff1fa..ec55ad7f588e8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -6,6 +6,7 @@ import moment from 'moment'; import sinon from 'sinon'; +import { ApiResponse, Context } from '@elastic/elasticsearch/lib/Transport'; import { alertsMock, AlertServicesMock } from '../../../../../alerts/server/mocks'; import { listMock } from '../../../../../lists/server/mocks'; @@ -28,6 +29,7 @@ import { getListsClient, getSignalTimeTuples, getExceptions, + hasTimestampFields, wrapBuildingBlocks, generateSignalId, createErrorsFromShard, @@ -61,6 +63,14 @@ const buildRuleMessage = buildRuleMessageFactory({ name: 'fake name', }); +const ruleStatusServiceMock = { + success: jest.fn(), + find: jest.fn(), + goingToRun: jest.fn(), + error: jest.fn(), + partialFailure: jest.fn(), +}; + describe('utils', () => { const anchor = '2020-01-01T06:06:06.666Z'; const unix = moment(anchor).valueOf(); @@ -803,6 +813,85 @@ describe('utils', () => { }); }); + describe('hasTimestampFields', () => { + test('returns true when missing timestamp override field', async () => { + const timestampField = 'event.ingested'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const timestampFieldCapsResponse: Partial, Context>> = { + body: { + fields: { + [timestampField]: { + date: { + type: 'date', + searchable: true, + aggregatable: true, + indices: ['myfakeindex-3', 'myfakeindex-4'], + }, + unmapped: { + type: 'unmapped', + searchable: false, + aggregatable: false, + indices: ['myfakeindex-1', 'myfakeindex-2'], + }, + }, + }, + }, + }; + mockLogger.error.mockClear(); + const res = await hasTimestampFields( + false, + timestampField, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + timestampFieldCapsResponse as ApiResponse>, + ruleStatusServiceMock, + mockLogger, + buildRuleMessage + ); + expect(mockLogger.error).toHaveBeenCalledWith( + 'The following indices are missing the timestamp override field "event.ingested": ["myfakeindex-1","myfakeindex-2"] name: "fake name" id: "fake id" rule id: "fake rule id" signals index: "fakeindex"' + ); + expect(res).toBeTruthy(); + }); + test('returns true when missing timestamp field', async () => { + const timestampField = '@timestamp'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const timestampFieldCapsResponse: Partial, Context>> = { + body: { + fields: { + [timestampField]: { + date: { + type: 'date', + searchable: true, + aggregatable: true, + indices: ['myfakeindex-3', 'myfakeindex-4'], + }, + unmapped: { + type: 'unmapped', + searchable: false, + aggregatable: false, + indices: ['myfakeindex-1', 'myfakeindex-2'], + }, + }, + }, + }, + }; + mockLogger.error.mockClear(); + const res = await hasTimestampFields( + false, + timestampField, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + timestampFieldCapsResponse as ApiResponse>, + ruleStatusServiceMock, + mockLogger, + buildRuleMessage + ); + expect(mockLogger.error).toHaveBeenCalledWith( + 'The following indices are missing the timestamp field "@timestamp": ["myfakeindex-1","myfakeindex-2"] name: "fake name" id: "fake id" rule id: "fake rule id" signals index: "fakeindex"' + ); + expect(res).toBeTruthy(); + }); + }); + describe('wrapBuildingBlocks', () => { it('should generate a unique id for each building block', () => { const wrappedBlocks = wrapBuildingBlocks( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index 23c5e6499c8ad..0ad502b67fbe6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -120,8 +120,10 @@ export const hasTimestampFields = async ( // if there is a timestamp override and the unmapped array for the timestamp override key is not empty, // partial failure const errorString = `The following indices are missing the ${ - timestampField === '@timestamp' ? 'timestamp field "@timestamp"' : 'timestamp override field' - } "${timestampField}": ${JSON.stringify( + timestampField === '@timestamp' + ? 'timestamp field "@timestamp"' + : `timestamp override field "${timestampField}"` + }: ${JSON.stringify( isEmpty(timestampFieldCapsResponse.body.fields) ? timestampFieldCapsResponse.body.indices : timestampFieldCapsResponse.body.fields[timestampField].unmapped.indices From ba37975fbc751e310bc921309acb97547fcd1f54 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Tue, 26 Jan 2021 08:41:23 -0600 Subject: [PATCH 13/21] Show legend on error rate chart (#89234) This probably was hidden for reasons related to implementing (or deferring the implementation of) comparisons. --- .../shared/charts/transaction_error_rate_chart/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx index 90877a895b05b..d712fa27c75ac 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_error_rate_chart/index.tsx @@ -77,7 +77,6 @@ export function TransactionErrorRateChart({ data: errorRates, type: 'linemark', color: theme.eui.euiColorVis7, - hideLegend: true, title: i18n.translate('xpack.apm.errorRate.chart.errorRate', { defaultMessage: 'Error rate (avg.)', }), From cb9afddb9163283682b797d5920f28c6c6dfb0a2 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 26 Jan 2021 08:35:23 -0700 Subject: [PATCH 14/21] [Maps] add video to maps docs (#89039) * [Maps] add video to maps docs * review feedback, revert some changes * move video to be below intro, clean up geojson upload section * Update docs/maps/index.asciidoc Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> --- docs/maps/index.asciidoc | 42 ++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/docs/maps/index.asciidoc b/docs/maps/index.asciidoc index 59b592ba1ec59..8f55697249fb2 100644 --- a/docs/maps/index.asciidoc +++ b/docs/maps/index.asciidoc @@ -9,28 +9,40 @@ [partintro] -- -Maps enables you to parse through your geographical data at scale, with speed, and in real time. With features like multiple layers and indices in a map, plotting of raw documents, dynamic client-side styling, and global search across multiple layers, you can understand and monitor your data with ease. +Create beautiful maps from your geographical data. With **Maps**, you can: -With Maps, you can: - -* Create maps with multiple layers and indices. -* Upload GeoJSON files into Elasticsearch. +* Build maps with multiple layers and indices. +* Upload GeoJSON. * Embed your map in dashboards. * Symbolize features using data values. -* Focus in on just the data you want. - -*Ready to get started?* Start your tour of Maps with the <>. +* Focus on only the data that’s important to you. + +*Ready to get started?* Watch the https://videos.elastic.co/watch/BYzRDtH4u7RSD8wKhuEW1b[video], and then start your tour of **Maps** with the <>. + +++++ + + +
+++++ [float] -=== Create maps with multiple layers and indices -You can use multiple layers and indices to show all your data in a single map. This enables your map to show how data sits relative to physical features like weather patterns, human-made features like international borders, and business-specific features like sales regions. You can plot individual documents or use aggregations to plot any data set, no matter how large. +=== Build maps with multiple layers and indices +Use multiple layers and indices to show all your data in a single map. Show how data sits relative to physical features like weather patterns, human-made features like international borders, and business-specific features like sales regions. Plot individual documents or use aggregations to plot any data set, no matter how large. [role="screenshot"] image::maps/images/sample_data_ecommerce.png[] [float] -=== Upload GeoJSON files into Elasticsearch -Maps makes it easy to import geospatial data into the Elastic Stack. Using the GeoJSON Upload feature, you can drag and drop your point and shape data files directly into Elasticsearch, and then use them as layers in the map. +=== Upload GeoJSON +Use **Maps** to drag and drop your GeoJSON points, lines, and polygons into Elasticsearch, and then use them as layers in your map. [float] === Embed your map in dashboards @@ -43,11 +55,11 @@ image::maps/images/embed_in_dashboard.jpeg[] [float] === Symbolize features using data values -You can customize each layer to highlight meaningful dimensions in your data. For example, you can use dark colors to symbolize areas with more web log traffic, and lighter colors to symbolize areas with less traffic. +Customize each layer to highlight meaningful dimensions in your data. For example, use dark colors to symbolize areas with more web log traffic, and lighter colors to symbolize areas with less traffic. [float] -=== Focus in on just the data you want -You can search across your Elasticsearch layers to focus in on just the data you want. Draw a polygon on the map or use the shape from features to create spatial filters to narrow search results to documents that either intersect with, are within, or do not intersect with the specified geometry. Filter individual layers to compares facets. +=== Focus on only the data that’s important to you +Search across your Elasticsearch layers to focus in on just the data you want. Combine free text search with field-based search using the <>. Set the time filter to restrict layers by time. Draw a polygon on the map or use the shape from features to create spatial filters. Filter individual layers to compares facets. -- From a4c884b92bdc081242e3f520f051222f35b9b6b9 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 26 Jan 2021 16:48:47 +0100 Subject: [PATCH 15/21] tsconfig file for lens (#89135) --- x-pack/plugins/lens/kibana.json | 1 - .../suffix_formatter.ts | 8 +++- x-pack/plugins/lens/tsconfig.json | 41 +++++++++++++++++++ x-pack/test/tsconfig.json | 1 + x-pack/tsconfig.json | 2 + x-pack/tsconfig.refs.json | 1 + 6 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/lens/tsconfig.json diff --git a/x-pack/plugins/lens/kibana.json b/x-pack/plugins/lens/kibana.json index 4ecc7f0128591..dc0a92ac702d0 100644 --- a/x-pack/plugins/lens/kibana.json +++ b/x-pack/plugins/lens/kibana.json @@ -12,7 +12,6 @@ "urlForwarding", "visualizations", "dashboard", - "charts", "uiActions", "embeddable", "share" diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/suffix_formatter.ts b/x-pack/plugins/lens/public/indexpattern_datasource/suffix_formatter.ts index 3d9f3be01a11b..26541c9f890b9 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/suffix_formatter.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/suffix_formatter.ts @@ -5,7 +5,11 @@ */ import { i18n } from '@kbn/i18n'; -import { FieldFormat, KBN_FIELD_TYPES } from '../../../../../src/plugins/data/public'; +import { + FieldFormat, + FieldFormatInstanceType, + KBN_FIELD_TYPES, +} from '../../../../../src/plugins/data/public'; import { FormatFactory } from '../types'; import { TimeScaleUnit } from './time_scale'; @@ -23,7 +27,7 @@ export const unitSuffixesLong: Record = { d: i18n.translate('xpack.lens.fieldFormats.longSuffix.d', { defaultMessage: 'per day' }), }; -export function getSuffixFormatter(formatFactory: FormatFactory) { +export function getSuffixFormatter(formatFactory: FormatFactory): FieldFormatInstanceType { return class SuffixFormatter extends FieldFormat { static id = 'suffix'; static title = i18n.translate('xpack.lens.fieldFormats.suffix.title', { diff --git a/x-pack/plugins/lens/tsconfig.json b/x-pack/plugins/lens/tsconfig.json new file mode 100644 index 0000000000000..7ac5a2980d0ba --- /dev/null +++ b/x-pack/plugins/lens/tsconfig.json @@ -0,0 +1,41 @@ + +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./target/types", + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + }, + "include": [ + "*.ts", + "common/**/*", + "public/**/*", + "server/**/*", + "../../typings/**/*" + ], + "references": [ + { "path": "../../../src/core/tsconfig.json" }, + { "path": "../task_manager/tsconfig.json" }, + { "path": "../global_search/tsconfig.json"}, + { "path": "../saved_objects_tagging/tsconfig.json"}, + { "path": "../../../src/plugins/data/tsconfig.json"}, + { "path": "../../../src/plugins/charts/tsconfig.json"}, + { "path": "../../../src/plugins/expressions/tsconfig.json"}, + { "path": "../../../src/plugins/navigation/tsconfig.json" }, + { "path": "../../../src/plugins/url_forwarding/tsconfig.json" }, + { "path": "../../../src/plugins/visualizations/tsconfig.json" }, + { "path": "../../../src/plugins/dashboard/tsconfig.json" }, + { "path": "../../../src/plugins/ui_actions/tsconfig.json" }, + { "path": "../../../src/plugins/embeddable/tsconfig.json" }, + { "path": "../../../src/plugins/share/tsconfig.json" }, + { "path": "../../../src/plugins/usage_collection/tsconfig.json" }, + { "path": "../../../src/plugins/saved_objects/tsconfig.json"}, + { "path": "../../../src/plugins/kibana_utils/tsconfig.json" }, + { "path": "../../../src/plugins/kibana_react/tsconfig.json" }, + { "path": "../../../src/plugins/embeddable/tsconfig.json"}, + { "path": "../../../src/plugins/lens_oss/tsconfig.json"}, + { "path": "../../../src/plugins/presentation_util/tsconfig.json"}, + ] + } \ No newline at end of file diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 699ff64af3f88..6368751fedf75 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -46,6 +46,7 @@ { "path": "../plugins/embeddable_enhanced/tsconfig.json" }, { "path": "../plugins/event_log/tsconfig.json" }, { "path": "../plugins/licensing/tsconfig.json" }, + { "path": "../plugins/lens/tsconfig.json" }, { "path": "../plugins/task_manager/tsconfig.json" }, { "path": "../plugins/telemetry_collection_xpack/tsconfig.json" }, { "path": "../plugins/triggers_actions_ui/tsconfig.json" }, diff --git a/x-pack/tsconfig.json b/x-pack/tsconfig.json index ae12773023663..a6eb098b5d678 100644 --- a/x-pack/tsconfig.json +++ b/x-pack/tsconfig.json @@ -18,6 +18,7 @@ "plugins/embeddable_enhanced/**/*", "plugins/event_log/**/*", "plugins/licensing/**/*", + "plugins/lens/**/*", "plugins/searchprofiler/**/*", "plugins/security_solution/cypress/**/*", "plugins/task_manager/**/*", @@ -84,6 +85,7 @@ { "path": "./plugins/embeddable_enhanced/tsconfig.json" }, { "path": "./plugins/event_log/tsconfig.json" }, { "path": "./plugins/licensing/tsconfig.json" }, + { "path": "./plugins/lens/tsconfig.json" }, { "path": "./plugins/searchprofiler/tsconfig.json" }, { "path": "./plugins/task_manager/tsconfig.json" }, { "path": "./plugins/telemetry_collection_xpack/tsconfig.json" }, diff --git a/x-pack/tsconfig.refs.json b/x-pack/tsconfig.refs.json index 02623b11ce314..6a9e54e2e7adf 100644 --- a/x-pack/tsconfig.refs.json +++ b/x-pack/tsconfig.refs.json @@ -5,6 +5,7 @@ { "path": "./plugins/alerts/tsconfig.json"}, { "path": "./plugins/dashboard_enhanced/tsconfig.json" }, { "path": "./plugins/licensing/tsconfig.json" }, + { "path": "./plugins/lens/tsconfig.json" }, { "path": "./plugins/console_extensions/tsconfig.json" }, { "path": "./plugins/discover_enhanced/tsconfig.json" }, { "path": "./plugins/data_enhanced/tsconfig.json" }, From 110e880fbf653cb6388eaf4c750874a9c24b48ed Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Tue, 26 Jan 2021 10:06:38 -0600 Subject: [PATCH 16/21] [Workplace Search] Add source logic and sources logic unit tests (#89247) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Move shared data to mock * Change name of mock Everywhere else we don’t use the “mock” prefix for mocked data so I’m changing here to match. Also added missing “size” prop from mock. * Remove unused actions These were missed on the migration to the new add_source_logic file. All of that logic lives there now * Add tests for source logic * REmove resetFlashMessages This is no longer used as Kibana resets its own. This was removed from the component already. * Export items for use in tests * Remove unnecessary condition It’s literally not possible for this function to receive an empty contentSources parameter. Not sure why this was added. Even if the server sends response with no privateContentSources, the reducer falls back to an empty array. * Add tests for sources logic * Fix typo --- .../__mocks__/content_sources.mock.ts | 11 + .../workplace_search/__mocks__/meta.mock.ts | 3 +- .../components/source_content.test.tsx | 17 +- .../content_sources/source_logic.test.ts | 444 ++++++++++++++++++ .../views/content_sources/source_logic.ts | 7 - .../content_sources/sources_logic.test.ts | 319 +++++++++++++ .../views/content_sources/sources_logic.ts | 16 +- .../views/groups/groups.test.tsx | 4 +- 8 files changed, 785 insertions(+), 36 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.test.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts index 0e0d1fa864033..efae95f83034e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts @@ -323,3 +323,14 @@ export const mostRecentIndexJob = { activeReindexJobId: '123', numDocumentsWithErrors: 1, }; + +export const contentItems = [ + { + id: '1234', + last_updated: '2021-01-21', + }, + { + id: '1235', + last_updated: '2021-01-20', + }, +]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/meta.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/meta.mock.ts index e596ea5d7e948..acfbad1400c66 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/meta.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/meta.mock.ts @@ -6,10 +6,11 @@ import { DEFAULT_META } from '../../shared/constants'; -export const mockMeta = { +export const meta = { ...DEFAULT_META, page: { current: 1, + size: 5, total_results: 50, total_pages: 5, }, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.test.tsx index c445a7aec04f6..a404ae508c130 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_content.test.tsx @@ -20,8 +20,8 @@ import { EuiLink, } from '@elastic/eui'; -import { mockMeta } from '../../../__mocks__/meta.mock'; -import { fullContentSources } from '../../../__mocks__/content_sources.mock'; +import { meta } from '../../../__mocks__/meta.mock'; +import { fullContentSources, contentItems } from '../../../__mocks__/content_sources.mock'; import { DEFAULT_META } from '../../../../shared/constants'; import { ComponentLoader } from '../../../components/shared/component_loader'; @@ -38,17 +38,8 @@ describe('SourceContent', () => { const mockValues = { contentSource: fullContentSources[0], - contentMeta: mockMeta, - contentItems: [ - { - id: '1234', - last_updated: '2021-01-21', - }, - { - id: '1235', - last_updated: '2021-01-20', - }, - ], + contentMeta: meta, + contentItems, contentFilterValue: '', dataLoading: false, sectionLoading: false, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts new file mode 100644 index 0000000000000..a0efbfe4aca1d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts @@ -0,0 +1,444 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + LogicMounter, + mockFlashMessageHelpers, + mockHttpValues, + mockKibanaValues, + expectedAsyncError, +} from '../../../__mocks__'; + +import { AppLogic } from '../../app_logic'; +jest.mock('../../app_logic', () => ({ + AppLogic: { values: { isOrganization: true } }, +})); + +import { + fullContentSources, + sourceConfigData, + contentItems, +} from '../../__mocks__/content_sources.mock'; +import { meta } from '../../__mocks__/meta.mock'; + +import { DEFAULT_META } from '../../../shared/constants'; +import { NOT_FOUND_PATH } from '../../routes'; + +import { SourceLogic } from './source_logic'; + +describe('SourceLogic', () => { + const { http } = mockHttpValues; + const { + clearFlashMessages, + flashAPIErrors, + setSuccessMessage, + setQueuedSuccessMessage, + } = mockFlashMessageHelpers; + const { navigateToUrl } = mockKibanaValues; + const { mount, getListeners } = new LogicMounter(SourceLogic); + + const contentSource = fullContentSources[0]; + + const defaultValues = { + contentSource: {}, + contentItems: [], + sourceConfigData: {}, + dataLoading: true, + sectionLoading: true, + buttonLoading: false, + contentMeta: DEFAULT_META, + contentFilterValue: '', + }; + + const searchServerResponse = { + results: contentItems, + meta, + }; + + beforeEach(() => { + jest.clearAllMocks(); + mount(); + }); + + it('has expected default values', () => { + expect(SourceLogic.values).toEqual(defaultValues); + }); + + describe('actions', () => { + it('onInitializeSource', () => { + SourceLogic.actions.onInitializeSource(contentSource); + + expect(SourceLogic.values.contentSource).toEqual(contentSource); + expect(SourceLogic.values.dataLoading).toEqual(false); + }); + + it('onUpdateSourceName', () => { + const NAME = 'foo'; + SourceLogic.actions.onInitializeSource(contentSource); + SourceLogic.actions.onUpdateSourceName(NAME); + + expect(SourceLogic.values.contentSource).toEqual({ + ...contentSource, + name: NAME, + }); + expect(setSuccessMessage).toHaveBeenCalled(); + }); + + it('setSourceConfigData', () => { + SourceLogic.actions.setSourceConfigData(sourceConfigData); + + expect(SourceLogic.values.sourceConfigData).toEqual(sourceConfigData); + expect(SourceLogic.values.dataLoading).toEqual(false); + }); + + it('setSearchResults', () => { + SourceLogic.actions.setSearchResults(searchServerResponse); + + expect(SourceLogic.values.contentItems).toEqual(contentItems); + expect(SourceLogic.values.contentMeta).toEqual(meta); + expect(SourceLogic.values.sectionLoading).toEqual(false); + }); + + it('setContentFilterValue', () => { + const VALUE = 'bar'; + SourceLogic.actions.setSearchResults(searchServerResponse); + SourceLogic.actions.onInitializeSource(contentSource); + SourceLogic.actions.setContentFilterValue(VALUE); + + expect(SourceLogic.values.contentMeta).toEqual({ + ...meta, + page: { + ...meta.page, + current: DEFAULT_META.page.current, + }, + }); + expect(SourceLogic.values.contentFilterValue).toEqual(VALUE); + }); + + it('setActivePage', () => { + const PAGE = 2; + SourceLogic.actions.setSearchResults(searchServerResponse); + SourceLogic.actions.setActivePage(PAGE); + + expect(SourceLogic.values.contentMeta).toEqual({ + ...meta, + page: { + ...meta.page, + current: PAGE, + }, + }); + }); + + it('setButtonNotLoading', () => { + // Set button state to loading + SourceLogic.actions.removeContentSource(contentSource.id); + SourceLogic.actions.setButtonNotLoading(); + + expect(SourceLogic.values.buttonLoading).toEqual(false); + }); + }); + + describe('listeners', () => { + describe('initializeSource', () => { + it('calls API and sets values (org)', async () => { + const onInitializeSourceSpy = jest.spyOn(SourceLogic.actions, 'onInitializeSource'); + const promise = Promise.resolve(contentSource); + http.get.mockReturnValue(promise); + SourceLogic.actions.initializeSource(contentSource.id); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/sources/123'); + await promise; + expect(onInitializeSourceSpy).toHaveBeenCalledWith(contentSource); + }); + + it('calls API and sets values (account)', async () => { + AppLogic.values.isOrganization = false; + + const onInitializeSourceSpy = jest.spyOn(SourceLogic.actions, 'onInitializeSource'); + const promise = Promise.resolve(contentSource); + http.get.mockReturnValue(promise); + SourceLogic.actions.initializeSource(contentSource.id); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/account/sources/123'); + await promise; + expect(onInitializeSourceSpy).toHaveBeenCalledWith(contentSource); + }); + + it('handles federated source', async () => { + AppLogic.values.isOrganization = false; + + const initializeFederatedSummarySpy = jest.spyOn( + SourceLogic.actions, + 'initializeFederatedSummary' + ); + const promise = Promise.resolve({ + ...contentSource, + isFederatedSource: true, + }); + http.get.mockReturnValue(promise); + SourceLogic.actions.initializeSource(contentSource.id); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/account/sources/123'); + await promise; + expect(initializeFederatedSummarySpy).toHaveBeenCalledWith(contentSource.id); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.get.mockReturnValue(promise); + SourceLogic.actions.initializeSource(contentSource.id); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + + it('handles not found state', async () => { + const error = { + response: { + error: 'this is an error', + status: 404, + }, + }; + const promise = Promise.reject(error); + http.get.mockReturnValue(promise); + SourceLogic.actions.initializeSource(contentSource.id); + await expectedAsyncError(promise); + + expect(navigateToUrl).toHaveBeenCalledWith(NOT_FOUND_PATH); + }); + }); + + describe('initializeFederatedSummary', () => { + it('calls API and sets values', async () => { + const onUpdateSummarySpy = jest.spyOn(SourceLogic.actions, 'onUpdateSummary'); + const promise = Promise.resolve(contentSource); + http.get.mockReturnValue(promise); + SourceLogic.actions.initializeFederatedSummary(contentSource.id); + + expect(http.get).toHaveBeenCalledWith( + '/api/workplace_search/org/sources/123/federated_summary' + ); + await promise; + expect(onUpdateSummarySpy).toHaveBeenCalledWith(contentSource.summary); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.get.mockReturnValue(promise); + SourceLogic.actions.initializeFederatedSummary(contentSource.id); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); + + describe('searchContentSourceDocuments', () => { + const mockBreakpoint = jest.fn(); + const values = { contentMeta: meta, contentFilterValue: '' }; + const actions = { setSearchResults: jest.fn() }; + const { searchContentSourceDocuments } = getListeners({ + values, + actions, + }); + + it('calls API and sets values (org)', async () => { + AppLogic.values.isOrganization = true; + const promise = Promise.resolve(searchServerResponse); + http.post.mockReturnValue(promise); + + await searchContentSourceDocuments({ sourceId: contentSource.id }, mockBreakpoint); + expect(http.post).toHaveBeenCalledWith('/api/workplace_search/org/sources/123/documents', { + body: JSON.stringify({ query: '', page: meta.page }), + }); + + await promise; + expect(actions.setSearchResults).toHaveBeenCalledWith(searchServerResponse); + }); + + it('calls API and sets values (account)', async () => { + AppLogic.values.isOrganization = false; + const promise = Promise.resolve(searchServerResponse); + http.post.mockReturnValue(promise); + + SourceLogic.actions.searchContentSourceDocuments(contentSource.id); + await searchContentSourceDocuments({ sourceId: contentSource.id }, mockBreakpoint); + expect(http.post).toHaveBeenCalledWith( + '/api/workplace_search/account/sources/123/documents', + { + body: JSON.stringify({ query: '', page: meta.page }), + } + ); + + await promise; + expect(actions.setSearchResults).toHaveBeenCalledWith(searchServerResponse); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.post.mockReturnValue(promise); + + await searchContentSourceDocuments({ sourceId: contentSource.id }, mockBreakpoint); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); + + describe('updateContentSource', () => { + it('calls API and sets values (org)', async () => { + AppLogic.values.isOrganization = true; + + const onUpdateSourceNameSpy = jest.spyOn(SourceLogic.actions, 'onUpdateSourceName'); + const promise = Promise.resolve(contentSource); + http.patch.mockReturnValue(promise); + SourceLogic.actions.updateContentSource(contentSource.id, contentSource); + + expect(http.patch).toHaveBeenCalledWith('/api/workplace_search/org/sources/123/settings', { + body: JSON.stringify({ content_source: contentSource }), + }); + await promise; + expect(onUpdateSourceNameSpy).toHaveBeenCalledWith(contentSource.name); + }); + + it('calls API and sets values (account)', async () => { + AppLogic.values.isOrganization = false; + + const onUpdateSourceNameSpy = jest.spyOn(SourceLogic.actions, 'onUpdateSourceName'); + const promise = Promise.resolve(contentSource); + http.patch.mockReturnValue(promise); + SourceLogic.actions.updateContentSource(contentSource.id, contentSource); + + expect(http.patch).toHaveBeenCalledWith( + '/api/workplace_search/account/sources/123/settings', + { + body: JSON.stringify({ content_source: contentSource }), + } + ); + await promise; + expect(onUpdateSourceNameSpy).toHaveBeenCalledWith(contentSource.name); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.patch.mockReturnValue(promise); + SourceLogic.actions.updateContentSource(contentSource.id, contentSource); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); + + describe('removeContentSource', () => { + it('calls API and sets values (org)', async () => { + AppLogic.values.isOrganization = true; + + const setButtonNotLoadingSpy = jest.spyOn(SourceLogic.actions, 'setButtonNotLoading'); + const promise = Promise.resolve(contentSource); + http.delete.mockReturnValue(promise); + SourceLogic.actions.removeContentSource(contentSource.id); + + expect(clearFlashMessages).toHaveBeenCalled(); + expect(http.delete).toHaveBeenCalledWith('/api/workplace_search/org/sources/123'); + await promise; + expect(setQueuedSuccessMessage).toHaveBeenCalled(); + expect(setButtonNotLoadingSpy).toHaveBeenCalled(); + }); + + it('calls API and sets values (account)', async () => { + AppLogic.values.isOrganization = false; + + const setButtonNotLoadingSpy = jest.spyOn(SourceLogic.actions, 'setButtonNotLoading'); + const promise = Promise.resolve(contentSource); + http.delete.mockReturnValue(promise); + SourceLogic.actions.removeContentSource(contentSource.id); + + expect(clearFlashMessages).toHaveBeenCalled(); + expect(http.delete).toHaveBeenCalledWith('/api/workplace_search/account/sources/123'); + await promise; + expect(setButtonNotLoadingSpy).toHaveBeenCalled(); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.delete.mockReturnValue(promise); + SourceLogic.actions.removeContentSource(contentSource.id); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); + + describe('getSourceConfigData', () => { + const serviceType = 'github'; + + it('calls API and sets values', async () => { + AppLogic.values.isOrganization = true; + + const setSourceConfigDataSpy = jest.spyOn(SourceLogic.actions, 'setSourceConfigData'); + const promise = Promise.resolve(contentSource); + http.get.mockReturnValue(promise); + SourceLogic.actions.getSourceConfigData(serviceType); + + expect(http.get).toHaveBeenCalledWith( + `/api/workplace_search/org/settings/connectors/${serviceType}` + ); + await promise; + expect(setSourceConfigDataSpy).toHaveBeenCalled(); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.get.mockReturnValue(promise); + SourceLogic.actions.getSourceConfigData(serviceType); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); + + it('resetSourceState', () => { + SourceLogic.actions.resetSourceState(); + + expect(clearFlashMessages).toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts index 2de70009c56a2..ba5c29c190f95 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts @@ -126,29 +126,22 @@ export const SourceLogic = kea>({ onInitializeSource: () => false, setSourceConfigData: () => false, resetSourceState: () => false, - setPreContentSourceConfigData: () => false, }, ], buttonLoading: [ false, { setButtonNotLoading: () => false, - setSourceConnectData: () => false, setSourceConfigData: () => false, resetSourceState: () => false, removeContentSource: () => true, - saveSourceConfig: () => true, - getSourceConnectData: () => true, - createContentSource: () => true, }, ], sectionLoading: [ true, { searchContentSourceDocuments: () => true, - getPreContentSourceConfigData: () => true, setSearchResults: () => false, - setPreContentSourceConfigData: () => false, }, ], contentItems: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.test.ts new file mode 100644 index 0000000000000..11e3a52081637 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.test.ts @@ -0,0 +1,319 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { + LogicMounter, + mockFlashMessageHelpers, + mockHttpValues, + expectedAsyncError, +} from '../../../__mocks__'; + +import { AppLogic } from '../../app_logic'; +jest.mock('../../app_logic', () => ({ + AppLogic: { values: { isOrganization: true } }, +})); + +import { configuredSources, contentSources } from '../../__mocks__/content_sources.mock'; + +import { SourcesLogic, fetchSourceStatuses, POLLING_INTERVAL } from './sources_logic'; + +describe('SourcesLogic', () => { + const { http } = mockHttpValues; + const { flashAPIErrors, setQueuedSuccessMessage } = mockFlashMessageHelpers; + const { mount, unmount } = new LogicMounter(SourcesLogic); + + const contentSource = contentSources[0]; + + const defaultValues = { + contentSources: [], + privateContentSources: [], + sourceData: [], + availableSources: [], + configuredSources: [], + serviceTypes: [], + permissionsModal: null, + dataLoading: true, + serverStatuses: null, + }; + + const serverStatuses = [ + { + id: '123', + name: 'my source', + service_type: 'github', + status: { + status: 'this is a thing', + synced_at: '2021-01-25', + error_reason: 1, + }, + }, + ]; + + const serverResponse = { + contentSources, + privateContentSources: contentSources, + serviceTypes: configuredSources, + }; + + beforeEach(() => { + jest.useFakeTimers(); + jest.clearAllMocks(); + mount(); + }); + + it('has expected default values', () => { + expect(SourcesLogic.values).toEqual(defaultValues); + }); + + it('handles unmounting', async () => { + unmount(); + expect(clearInterval).toHaveBeenCalled(); + }); + + describe('actions', () => { + describe('onInitializeSources', () => { + it('sets values', () => { + SourcesLogic.actions.onInitializeSources(serverResponse); + + expect(SourcesLogic.values.contentSources).toEqual(contentSources); + expect(SourcesLogic.values.privateContentSources).toEqual(contentSources); + expect(SourcesLogic.values.serviceTypes).toEqual(configuredSources); + expect(SourcesLogic.values.dataLoading).toEqual(false); + }); + + it('fallbacks', () => { + SourcesLogic.actions.onInitializeSources({ + contentSources, + serviceTypes: undefined as any, + }); + + expect(SourcesLogic.values.serviceTypes).toEqual([]); + expect(SourcesLogic.values.privateContentSources).toEqual([]); + }); + }); + + it('setServerSourceStatuses', () => { + SourcesLogic.actions.setServerSourceStatuses(serverStatuses); + const source = serverStatuses[0]; + + expect(SourcesLogic.values.serverStatuses).toEqual({ + [source.id]: source.status.status, + }); + }); + + it('onSetSearchability', () => { + const id = contentSources[0].id; + const updatedSources = [...contentSources]; + updatedSources[0].searchable = false; + SourcesLogic.actions.onInitializeSources(serverResponse); + SourcesLogic.actions.onSetSearchability(id, false); + + expect(SourcesLogic.values.contentSources).toEqual(updatedSources); + expect(SourcesLogic.values.privateContentSources).toEqual(updatedSources); + }); + + describe('setAddedSource', () => { + it('configured', () => { + const name = contentSources[0].name; + SourcesLogic.actions.setAddedSource(name, false, 'custom'); + + expect(SourcesLogic.values.permissionsModal).toEqual({ + addedSourceName: name, + additionalConfiguration: false, + serviceType: 'custom', + }); + expect(setQueuedSuccessMessage).toHaveBeenCalledWith('Successfully connected source. '); + }); + + it('unconfigured', () => { + const name = contentSources[0].name; + SourcesLogic.actions.setAddedSource(name, true, 'custom'); + + expect(SourcesLogic.values.permissionsModal).toEqual({ + addedSourceName: name, + additionalConfiguration: true, + serviceType: 'custom', + }); + expect(setQueuedSuccessMessage).toHaveBeenCalledWith( + 'Successfully connected source. This source requires additional configuration.' + ); + }); + }); + + it('resetPermissionsModal', () => { + SourcesLogic.actions.resetPermissionsModal(); + + expect(SourcesLogic.values.permissionsModal).toEqual(null); + }); + }); + + describe('listeners', () => { + describe('initializeSources', () => { + it('calls API and sets values (org)', async () => { + AppLogic.values.isOrganization = true; + const pollForSourceStatusChangesSpy = jest.spyOn( + SourcesLogic.actions, + 'pollForSourceStatusChanges' + ); + const onInitializeSourcesSpy = jest.spyOn(SourcesLogic.actions, 'onInitializeSources'); + const promise = Promise.resolve(contentSources); + http.get.mockReturnValue(promise); + SourcesLogic.actions.initializeSources(); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/sources'); + await promise; + expect(pollForSourceStatusChangesSpy).toHaveBeenCalled(); + expect(onInitializeSourcesSpy).toHaveBeenCalledWith(contentSources); + }); + + it('calls API (account)', async () => { + AppLogic.values.isOrganization = false; + const promise = Promise.resolve(contentSource); + http.get.mockReturnValue(promise); + SourcesLogic.actions.initializeSources(); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/account/sources'); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.get.mockReturnValue(promise); + SourcesLogic.actions.initializeSources(); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); + + describe('setSourceSearchability', () => { + const id = contentSources[0].id; + + it('calls API and sets values (org)', async () => { + AppLogic.values.isOrganization = true; + const onSetSearchability = jest.spyOn(SourcesLogic.actions, 'onSetSearchability'); + const promise = Promise.resolve(contentSources); + http.put.mockReturnValue(promise); + SourcesLogic.actions.setSourceSearchability(id, true); + + expect(http.put).toHaveBeenCalledWith('/api/workplace_search/org/sources/123/searchable', { + body: JSON.stringify({ searchable: true }), + }); + await promise; + expect(onSetSearchability).toHaveBeenCalledWith(id, true); + }); + + it('calls API (account)', async () => { + AppLogic.values.isOrganization = false; + const promise = Promise.resolve(contentSource); + http.put.mockReturnValue(promise); + SourcesLogic.actions.setSourceSearchability(id, true); + + expect(http.put).toHaveBeenCalledWith( + '/api/workplace_search/account/sources/123/searchable', + { + body: JSON.stringify({ searchable: true }), + } + ); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.put.mockReturnValue(promise); + SourcesLogic.actions.setSourceSearchability(id, true); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); + + describe('pollForSourceStatusChanges', () => { + it('calls API and sets values', async () => { + AppLogic.values.isOrganization = true; + SourcesLogic.actions.setServerSourceStatuses(serverStatuses); + + const setServerSourceStatusesSpy = jest.spyOn( + SourcesLogic.actions, + 'setServerSourceStatuses' + ); + const promise = Promise.resolve(contentSources); + http.get.mockReturnValue(promise); + SourcesLogic.actions.pollForSourceStatusChanges(); + + jest.advanceTimersByTime(POLLING_INTERVAL); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/sources/status'); + await promise; + expect(setServerSourceStatusesSpy).toHaveBeenCalledWith(contentSources); + }); + }); + + it('resetSourcesState', () => { + SourcesLogic.actions.resetSourcesState(); + + expect(clearInterval).toHaveBeenCalled(); + }); + }); + + describe('selectors', () => { + it('availableSources & configuredSources have correct length', () => { + SourcesLogic.actions.onInitializeSources(serverResponse); + + expect(SourcesLogic.values.availableSources).toHaveLength(1); + expect(SourcesLogic.values.configuredSources).toHaveLength(5); + }); + }); + + describe('fetchSourceStatuses', () => { + it('calls API and sets values (org)', async () => { + const setServerSourceStatusesSpy = jest.spyOn( + SourcesLogic.actions, + 'setServerSourceStatuses' + ); + const promise = Promise.resolve(contentSources); + http.get.mockReturnValue(promise); + fetchSourceStatuses(true); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/org/sources/status'); + await promise; + expect(setServerSourceStatusesSpy).toHaveBeenCalledWith(contentSources); + }); + + it('calls API (account)', async () => { + const promise = Promise.resolve(contentSource); + http.get.mockReturnValue(promise); + fetchSourceStatuses(false); + + expect(http.get).toHaveBeenCalledWith('/api/workplace_search/account/sources/status'); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.get.mockReturnValue(promise); + fetchSourceStatuses(true); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts index 0a3d047796f49..57e1a97e7bdf6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/sources_logic.ts @@ -12,11 +12,7 @@ import { i18n } from '@kbn/i18n'; import { HttpLogic } from '../../../shared/http'; -import { - flashAPIErrors, - setQueuedSuccessMessage, - clearFlashMessages, -} from '../../../shared/flash_messages'; +import { flashAPIErrors, setQueuedSuccessMessage } from '../../../shared/flash_messages'; import { Connector, ContentSourceDetails, ContentSourceStatus, SourceDataItem } from '../../types'; @@ -40,7 +36,6 @@ export interface ISourcesActions { additionalConfiguration: boolean, serviceType: string ): { addedSourceName: string; additionalConfiguration: boolean; serviceType: string }; - resetFlashMessages(): void; resetPermissionsModal(): void; resetSourcesState(): void; initializeSources(): void; @@ -78,7 +73,7 @@ interface ISourcesServerResponse { } let pollingInterval: number; -const POLLING_INTERVAL = 10000; +export const POLLING_INTERVAL = 10000; export const SourcesLogic = kea>({ path: ['enterprise_search', 'workplace_search', 'sources_logic'], @@ -91,7 +86,6 @@ export const SourcesLogic = kea>( additionalConfiguration: boolean, serviceType: string ) => ({ addedSourceName, additionalConfiguration, serviceType }), - resetFlashMessages: () => true, resetPermissionsModal: () => true, resetSourcesState: () => true, initializeSources: () => true, @@ -238,9 +232,6 @@ export const SourcesLogic = kea>( ].join(' ') ); }, - resetFlashMessages: () => { - clearFlashMessages(); - }, resetSourcesState: () => { clearInterval(pollingInterval); }, @@ -252,7 +243,7 @@ export const SourcesLogic = kea>( }), }); -const fetchSourceStatuses = async (isOrganization: boolean) => { +export const fetchSourceStatuses = async (isOrganization: boolean) => { const route = isOrganization ? '/api/workplace_search/org/sources/status' : '/api/workplace_search/account/sources/status'; @@ -273,7 +264,6 @@ const updateSourcesOnToggle = ( sourceId: string, searchable: boolean ): ContentSourceDetails[] => { - if (!contentSources) return []; const sources = cloneDeep(contentSources) as ContentSourceDetails[]; const index = findIndex(sources, ({ id }) => id === sourceId); const updatedSource = sources[index]; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx index 7c746f75ffc94..30f345d8e017e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx @@ -7,7 +7,7 @@ import '../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../__mocks__'; import { groups } from '../../__mocks__/groups.mock'; -import { mockMeta } from '../../__mocks__/meta.mock'; +import { meta } from '../../__mocks__/meta.mock'; import React from 'react'; import { shallow } from 'enzyme'; @@ -46,7 +46,7 @@ const mockValues = { newGroup: null, groupListLoading: false, hasFiltersSet: false, - groupsMeta: mockMeta, + groupsMeta: meta, filteredSources: [], filteredUsers: [], filterValue: '', From b35a4e645d2ae2a4f44a8e127bd75d4b53e2ab50 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Tue, 26 Jan 2021 17:36:44 +0100 Subject: [PATCH 17/21] [ML] Fix swim lane time selection with a single time point and the Watcher URL (#89125) * [ML] fix swim lane selected times with only start boundaries * [ML] unit test * [ML] update url variables * [ML] selectedLanes to an array type * [ML] handle legacy query params --- .../ml/common/types/ml_url_generator.ts | 13 ++++++- .../explorer/hooks/use_selected_cells.test.ts | 34 +++++++++++++++++ .../explorer/hooks/use_selected_cells.ts | 37 +++++++++++++------ .../components/create_watch_flyout/email.html | 2 +- 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/ml/common/types/ml_url_generator.ts b/x-pack/plugins/ml/common/types/ml_url_generator.ts index 3ff57fc622da4..d7fded8299952 100644 --- a/x-pack/plugins/ml/common/types/ml_url_generator.ts +++ b/x-pack/plugins/ml/common/types/ml_url_generator.ts @@ -93,7 +93,18 @@ export interface ExplorerAppState { mlExplorerSwimlane: { selectedType?: 'overall' | 'viewBy'; selectedLanes?: string[]; - selectedTimes?: [number, number]; + /** + * @deprecated legacy query param variable, use `selectedLanes` + */ + selectedLane?: string[] | string; + /** + * It's possible to have only "from" time boundaries, e.g. in the Watcher URL + */ + selectedTimes?: [number, number] | number; + /** + * @deprecated legacy query param variable, use `selectedTimes` + */ + selectedTime?: [number, number] | number; showTopFieldValues?: boolean; viewByFieldName?: string; viewByPerPage?: number; diff --git a/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.test.ts b/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.test.ts index 08c8d11987f19..2308d4ae4f15c 100644 --- a/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.test.ts +++ b/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.test.ts @@ -130,4 +130,38 @@ describe('useSelectedCells', () => { }, }); }); + + test('should extend single time point selection with a bucket interval value', () => { + (useTimefilter() as jest.Mocked).getBounds.mockReturnValue({ + min: moment(1498824778 * 1000), + max: moment(1502366798 * 1000), + }); + + const urlState = { + mlExplorerSwimlane: { + selectedType: 'overall', + selectedLanes: ['Overall'], + selectedTimes: 1498780800, + showTopFieldValues: true, + viewByFieldName: 'apache2.access.remote_ip', + viewByFromPage: 1, + viewByPerPage: 10, + }, + mlExplorerFilter: {}, + } as ExplorerAppState; + + const setUrlState = jest.fn(); + + const bucketInterval = 86400; + + const { result } = renderHook(() => useSelectedCells(urlState, setUrlState, bucketInterval)); + + expect(result.current[0]).toEqual({ + lanes: ['Overall'], + showTopFieldValues: true, + times: [1498780800, 1498867200], + type: 'overall', + viewByFieldName: 'apache2.access.remote_ip', + }); + }); }); diff --git a/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.ts b/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.ts index 4ce828b0b7633..becc6197af888 100644 --- a/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.ts +++ b/x-pack/plugins/ml/public/application/explorer/hooks/use_selected_cells.ts @@ -19,18 +19,33 @@ export const useSelectedCells = ( const timeBounds = timeFilter.getBounds(); // keep swimlane selection, restore selectedCells from AppState - const selectedCells = useMemo(() => { - return appState?.mlExplorerSwimlane?.selectedType !== undefined - ? { - type: appState.mlExplorerSwimlane.selectedType, - lanes: appState.mlExplorerSwimlane.selectedLanes!, - times: appState.mlExplorerSwimlane.selectedTimes!, - showTopFieldValues: appState.mlExplorerSwimlane.showTopFieldValues, - viewByFieldName: appState.mlExplorerSwimlane.viewByFieldName, - } - : undefined; + const selectedCells: AppStateSelectedCells | undefined = useMemo(() => { + if (!appState?.mlExplorerSwimlane?.selectedType) { + return; + } + + let times = + appState.mlExplorerSwimlane.selectedTimes ?? appState.mlExplorerSwimlane.selectedTime!; + if (typeof times === 'number' && bucketIntervalInSeconds) { + times = [times, times + bucketIntervalInSeconds]; + } + + let lanes = + appState.mlExplorerSwimlane.selectedLanes ?? appState.mlExplorerSwimlane.selectedLane!; + + if (typeof lanes === 'string') { + lanes = [lanes]; + } + + return { + type: appState.mlExplorerSwimlane.selectedType, + lanes, + times, + showTopFieldValues: appState.mlExplorerSwimlane.showTopFieldValues, + viewByFieldName: appState.mlExplorerSwimlane.viewByFieldName, + } as AppStateSelectedCells; // TODO fix appState to use memoization - }, [JSON.stringify(appState?.mlExplorerSwimlane)]); + }, [JSON.stringify(appState?.mlExplorerSwimlane), bucketIntervalInSeconds]); const setSelectedCells = useCallback( (swimlaneSelectedCells?: AppStateSelectedCells) => { diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/email.html b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/email.html index 2e93c7eefcf1e..713a68ba0c036 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/email.html +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/create_watch_flyout/email.html @@ -22,7 +22,7 @@

-
+ <%= openInAnomalyExplorerLinkText %>
From 1f644e44c97ecd6e3a522bcbc4cb25b3ec42c3aa Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 26 Jan 2021 17:42:41 +0100 Subject: [PATCH 18/21] Update babel to v7.12 (#89006) * bump babel version * build kbn-pm * fix integration test * remove cicular dependency between files which crashes Kibana in rutime Co-authored-by: spalger --- package.json | 48 +- packages/kbn-pm/dist/index.js | 926 ++++++++--------- .../reporting/server/lib/layouts/index.ts | 4 +- .../reporting/server/lib/layouts/layout.ts | 4 +- .../server/lib/layouts/preserve_layout.ts | 3 +- .../server/lib/layouts/print_layout.ts | 3 +- yarn.lock | 971 +++++++++++++++++- 7 files changed, 1371 insertions(+), 588 deletions(-) diff --git a/package.json b/package.json index dac83dacf6fbf..d14c5b0a7dc5f 100644 --- a/package.json +++ b/package.json @@ -93,8 +93,8 @@ "yarn": "^1.21.1" }, "dependencies": { - "@babel/core": "^7.11.6", - "@babel/runtime": "^7.11.2", + "@babel/core": "^7.12.10", + "@babel/runtime": "^7.12.5", "@elastic/datemath": "link:packages/elastic-datemath", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary", "@elastic/ems-client": "7.11.0", @@ -330,22 +330,22 @@ "yauzl": "^2.10.0" }, "devDependencies": { - "@babel/cli": "^7.10.5", - "@babel/parser": "^7.11.2", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/plugin-proposal-export-namespace-from": "^7.10.4", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", - "@babel/plugin-proposal-object-rest-spread": "^7.11.0", - "@babel/plugin-proposal-optional-chaining": "^7.11.0", - "@babel/plugin-proposal-private-methods": "^7.10.4", - "@babel/plugin-transform-modules-commonjs": "^7.10.4", - "@babel/plugin-transform-runtime": "^7.11.0", - "@babel/preset-env": "^7.11.0", - "@babel/preset-react": "^7.10.4", - "@babel/preset-typescript": "^7.10.4", - "@babel/register": "^7.10.5", - "@babel/traverse": "^7.11.5", - "@babel/types": "^7.11.0", + "@babel/cli": "^7.12.10", + "@babel/parser": "^7.12.11", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-export-namespace-from": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-runtime": "^7.12.10", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@babel/register": "^7.12.10", + "@babel/traverse": "^7.12.12", + "@babel/types": "^7.12.12", "@cypress/snapshot": "^2.1.7", "@cypress/webpack-preprocessor": "^5.5.0", "@elastic/apm-rum": "^5.6.1", @@ -407,7 +407,7 @@ "@types/angular": "^1.6.56", "@types/angular-mocks": "^1.7.0", "@types/archiver": "^5.1.0", - "@types/babel__core": "^7.1.10", + "@types/babel__core": "^7.1.12", "@types/base64-js": "^1.2.5", "@types/bluebird": "^3.1.1", "@types/chance": "^1.0.0", @@ -580,10 +580,10 @@ "argsplit": "^1.0.5", "autoprefixer": "^9.7.4", "axe-core": "^4.0.2", - "babel-eslint": "^10.0.3", - "babel-jest": "^26.3.0", - "babel-loader": "^8.0.6", - "babel-plugin-add-module-exports": "^1.0.2", + "babel-eslint": "^10.1.0", + "babel-jest": "^26.6.3", + "babel-loader": "^8.2.2", + "babel-plugin-add-module-exports": "^1.0.4", "babel-plugin-istanbul": "^6.0.0", "babel-plugin-require-context-hook": "^1.0.0", "babel-plugin-styled-components": "^1.10.7", @@ -629,7 +629,7 @@ "eslint-import-resolver-node": "0.3.2", "eslint-import-resolver-webpack": "0.11.1", "eslint-module-utils": "2.5.0", - "eslint-plugin-babel": "^5.3.0", + "eslint-plugin-babel": "^5.3.1", "eslint-plugin-ban": "^1.4.0", "eslint-plugin-cypress": "^2.11.2", "eslint-plugin-eslint-comments": "^3.2.0", diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 0c74315d0f3fb..09995a9be30a6 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -59381,11 +59381,11 @@ const os = __webpack_require__(121); const pMap = __webpack_require__(513); const arrify = __webpack_require__(508); const globby = __webpack_require__(514); -const hasGlob = __webpack_require__(714); -const cpFile = __webpack_require__(716); -const junk = __webpack_require__(726); -const pFilter = __webpack_require__(727); -const CpyError = __webpack_require__(729); +const hasGlob = __webpack_require__(710); +const cpFile = __webpack_require__(712); +const junk = __webpack_require__(722); +const pFilter = __webpack_require__(723); +const CpyError = __webpack_require__(725); const defaultOptions = { ignoreJunk: true @@ -59633,8 +59633,8 @@ const fs = __webpack_require__(134); const arrayUnion = __webpack_require__(515); const glob = __webpack_require__(147); const fastGlob = __webpack_require__(517); -const dirGlob = __webpack_require__(707); -const gitignore = __webpack_require__(710); +const dirGlob = __webpack_require__(703); +const gitignore = __webpack_require__(706); const DEFAULT_FILTER = () => false; @@ -59885,11 +59885,11 @@ module.exports.generateTasks = pkg.generateTasks; Object.defineProperty(exports, "__esModule", { value: true }); var optionsManager = __webpack_require__(519); var taskManager = __webpack_require__(520); -var reader_async_1 = __webpack_require__(678); -var reader_stream_1 = __webpack_require__(702); -var reader_sync_1 = __webpack_require__(703); -var arrayUtils = __webpack_require__(705); -var streamUtils = __webpack_require__(706); +var reader_async_1 = __webpack_require__(674); +var reader_stream_1 = __webpack_require__(698); +var reader_sync_1 = __webpack_require__(699); +var arrayUtils = __webpack_require__(701); +var streamUtils = __webpack_require__(702); /** * Synchronous API. */ @@ -60470,16 +60470,16 @@ module.exports.win32 = win32; var util = __webpack_require__(112); var braces = __webpack_require__(526); var toRegex = __webpack_require__(527); -var extend = __webpack_require__(644); +var extend = __webpack_require__(640); /** * Local dependencies */ -var compilers = __webpack_require__(646); -var parsers = __webpack_require__(673); -var cache = __webpack_require__(674); -var utils = __webpack_require__(675); +var compilers = __webpack_require__(642); +var parsers = __webpack_require__(669); +var cache = __webpack_require__(670); +var utils = __webpack_require__(671); var MAX_LENGTH = 1024 * 64; /** @@ -61360,8 +61360,8 @@ var extend = __webpack_require__(550); */ var compilers = __webpack_require__(552); -var parsers = __webpack_require__(567); -var Braces = __webpack_require__(571); +var parsers = __webpack_require__(565); +var Braces = __webpack_require__(569); var utils = __webpack_require__(553); var MAX_LENGTH = 1024 * 64; var cache = {}; @@ -63801,7 +63801,7 @@ utils.extend = __webpack_require__(550); utils.flatten = __webpack_require__(557); utils.isObject = __webpack_require__(535); utils.fillRange = __webpack_require__(558); -utils.repeat = __webpack_require__(566); +utils.repeat = __webpack_require__(564); utils.unique = __webpack_require__(549); utils.define = function(obj, key, val) { @@ -64444,9 +64444,9 @@ function flat(arr, res) { var util = __webpack_require__(112); var isNumber = __webpack_require__(559); -var extend = __webpack_require__(562); -var repeat = __webpack_require__(564); -var toRegex = __webpack_require__(565); +var extend = __webpack_require__(550); +var repeat = __webpack_require__(562); +var toRegex = __webpack_require__(563); /** * Return a range of numbers or letters. @@ -64825,66 +64825,6 @@ function isSlowBuffer (obj) { /* 562 */ /***/ (function(module, exports, __webpack_require__) { -"use strict"; - - -var isObject = __webpack_require__(563); - -module.exports = function extend(o/*, objects*/) { - if (!isObject(o)) { o = {}; } - - var len = arguments.length; - for (var i = 1; i < len; i++) { - var obj = arguments[i]; - - if (isObject(obj)) { - assign(o, obj); - } - } - return o; -}; - -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; - } - } -} - -/** - * Returns true if the given `key` is an own property of `obj`. - */ - -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - - -/***/ }), -/* 563 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -module.exports = function isExtendable(val) { - return typeof val !== 'undefined' && val !== null - && (typeof val === 'object' || typeof val === 'function'); -}; - - -/***/ }), -/* 564 */ -/***/ (function(module, exports, __webpack_require__) { - "use strict"; /*! * repeat-string @@ -64959,7 +64899,7 @@ function repeat(str, num) { /***/ }), -/* 565 */ +/* 563 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -64972,7 +64912,7 @@ function repeat(str, num) { -var repeat = __webpack_require__(564); +var repeat = __webpack_require__(562); var isNumber = __webpack_require__(559); var cache = {}; @@ -65260,7 +65200,7 @@ module.exports = toRegexRange; /***/ }), -/* 566 */ +/* 564 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -65285,13 +65225,13 @@ module.exports = function repeat(ele, num) { /***/ }), -/* 567 */ +/* 565 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Node = __webpack_require__(568); +var Node = __webpack_require__(566); var utils = __webpack_require__(553); /** @@ -65652,15 +65592,15 @@ function concatNodes(pos, node, parent, options) { /***/ }), -/* 568 */ +/* 566 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var isObject = __webpack_require__(535); -var define = __webpack_require__(569); -var utils = __webpack_require__(570); +var define = __webpack_require__(567); +var utils = __webpack_require__(568); var ownNames; /** @@ -66151,7 +66091,7 @@ exports = module.exports = Node; /***/ }), -/* 569 */ +/* 567 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -66189,7 +66129,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 570 */ +/* 568 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67215,16 +67155,16 @@ function assert(val, message) { /***/ }), -/* 571 */ +/* 569 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var extend = __webpack_require__(550); -var Snapdragon = __webpack_require__(572); +var Snapdragon = __webpack_require__(570); var compilers = __webpack_require__(552); -var parsers = __webpack_require__(567); +var parsers = __webpack_require__(565); var utils = __webpack_require__(553); /** @@ -67326,17 +67266,17 @@ module.exports = Braces; /***/ }), -/* 572 */ +/* 570 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var Base = __webpack_require__(573); -var define = __webpack_require__(602); -var Compiler = __webpack_require__(612); -var Parser = __webpack_require__(641); -var utils = __webpack_require__(621); +var Base = __webpack_require__(571); +var define = __webpack_require__(598); +var Compiler = __webpack_require__(608); +var Parser = __webpack_require__(637); +var utils = __webpack_require__(617); var regexCache = {}; var cache = {}; @@ -67507,20 +67447,20 @@ module.exports.Parser = Parser; /***/ }), -/* 573 */ +/* 571 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var define = __webpack_require__(574); -var CacheBase = __webpack_require__(575); -var Emitter = __webpack_require__(576); +var define = __webpack_require__(572); +var CacheBase = __webpack_require__(573); +var Emitter = __webpack_require__(574); var isObject = __webpack_require__(535); -var merge = __webpack_require__(596); -var pascal = __webpack_require__(599); -var cu = __webpack_require__(600); +var merge = __webpack_require__(592); +var pascal = __webpack_require__(595); +var cu = __webpack_require__(596); /** * Optionally define a custom `cache` namespace to use. @@ -67949,7 +67889,7 @@ module.exports.namespace = namespace; /***/ }), -/* 574 */ +/* 572 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -67987,21 +67927,21 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 575 */ +/* 573 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var isObject = __webpack_require__(535); -var Emitter = __webpack_require__(576); -var visit = __webpack_require__(577); -var toPath = __webpack_require__(580); -var union = __webpack_require__(581); -var del = __webpack_require__(587); -var get = __webpack_require__(584); -var has = __webpack_require__(592); -var set = __webpack_require__(595); +var Emitter = __webpack_require__(574); +var visit = __webpack_require__(575); +var toPath = __webpack_require__(578); +var union = __webpack_require__(579); +var del = __webpack_require__(583); +var get = __webpack_require__(581); +var has = __webpack_require__(588); +var set = __webpack_require__(591); /** * Create a `Cache` constructor that when instantiated will @@ -68255,7 +68195,7 @@ module.exports.namespace = namespace; /***/ }), -/* 576 */ +/* 574 */ /***/ (function(module, exports, __webpack_require__) { @@ -68424,7 +68364,7 @@ Emitter.prototype.hasListeners = function(event){ /***/ }), -/* 577 */ +/* 575 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68437,8 +68377,8 @@ Emitter.prototype.hasListeners = function(event){ -var visit = __webpack_require__(578); -var mapVisit = __webpack_require__(579); +var visit = __webpack_require__(576); +var mapVisit = __webpack_require__(577); module.exports = function(collection, method, val) { var result; @@ -68461,7 +68401,7 @@ module.exports = function(collection, method, val) { /***/ }), -/* 578 */ +/* 576 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68501,14 +68441,14 @@ module.exports = function visit(thisArg, method, target, val) { /***/ }), -/* 579 */ +/* 577 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var visit = __webpack_require__(578); +var visit = __webpack_require__(576); /** * Map `visit` over an array of objects. @@ -68545,7 +68485,7 @@ function isObject(val) { /***/ }), -/* 580 */ +/* 578 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68585,16 +68525,16 @@ function filter(arr) { /***/ }), -/* 581 */ +/* 579 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isObject = __webpack_require__(582); -var union = __webpack_require__(583); -var get = __webpack_require__(584); -var set = __webpack_require__(585); +var isObject = __webpack_require__(551); +var union = __webpack_require__(580); +var get = __webpack_require__(581); +var set = __webpack_require__(582); module.exports = function unionValue(obj, prop, value) { if (!isObject(obj)) { @@ -68622,27 +68562,7 @@ function arrayify(val) { /***/ }), -/* 582 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/*! - * is-extendable - * - * Copyright (c) 2015, Jon Schlinkert. - * Licensed under the MIT License. - */ - - - -module.exports = function isExtendable(val) { - return typeof val !== 'undefined' && val !== null - && (typeof val === 'object' || typeof val === 'function'); -}; - - -/***/ }), -/* 583 */ +/* 580 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68678,7 +68598,7 @@ module.exports = function union(init) { /***/ }), -/* 584 */ +/* 581 */ /***/ (function(module, exports) { /*! @@ -68734,7 +68654,7 @@ function toString(val) { /***/ }), -/* 585 */ +/* 582 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68748,9 +68668,9 @@ function toString(val) { var split = __webpack_require__(554); -var extend = __webpack_require__(586); +var extend = __webpack_require__(550); var isPlainObject = __webpack_require__(544); -var isObject = __webpack_require__(582); +var isObject = __webpack_require__(551); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -68796,47 +68716,7 @@ function isValidKey(key) { /***/ }), -/* 586 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isObject = __webpack_require__(582); - -module.exports = function extend(o/*, objects*/) { - if (!isObject(o)) { o = {}; } - - var len = arguments.length; - for (var i = 1; i < len; i++) { - var obj = arguments[i]; - - if (isObject(obj)) { - assign(o, obj); - } - } - return o; -}; - -function assign(a, b) { - for (var key in b) { - if (hasOwn(b, key)) { - a[key] = b[key]; - } - } -} - -/** - * Returns true if the given `key` is an own property of `obj`. - */ - -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} - - -/***/ }), -/* 587 */ +/* 583 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68850,7 +68730,7 @@ function hasOwn(obj, key) { var isObject = __webpack_require__(535); -var has = __webpack_require__(588); +var has = __webpack_require__(584); module.exports = function unset(obj, prop) { if (!isObject(obj)) { @@ -68875,7 +68755,7 @@ module.exports = function unset(obj, prop) { /***/ }), -/* 588 */ +/* 584 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68888,9 +68768,9 @@ module.exports = function unset(obj, prop) { -var isObject = __webpack_require__(589); -var hasValues = __webpack_require__(591); -var get = __webpack_require__(584); +var isObject = __webpack_require__(585); +var hasValues = __webpack_require__(587); +var get = __webpack_require__(581); module.exports = function(obj, prop, noZero) { if (isObject(obj)) { @@ -68901,7 +68781,7 @@ module.exports = function(obj, prop, noZero) { /***/ }), -/* 589 */ +/* 585 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68914,7 +68794,7 @@ module.exports = function(obj, prop, noZero) { -var isArray = __webpack_require__(590); +var isArray = __webpack_require__(586); module.exports = function isObject(val) { return val != null && typeof val === 'object' && isArray(val) === false; @@ -68922,7 +68802,7 @@ module.exports = function isObject(val) { /***/ }), -/* 590 */ +/* 586 */ /***/ (function(module, exports) { var toString = {}.toString; @@ -68933,7 +68813,7 @@ module.exports = Array.isArray || function (arr) { /***/ }), -/* 591 */ +/* 587 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68976,7 +68856,7 @@ module.exports = function hasValue(o, noZero) { /***/ }), -/* 592 */ +/* 588 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -68990,8 +68870,8 @@ module.exports = function hasValue(o, noZero) { var isObject = __webpack_require__(535); -var hasValues = __webpack_require__(593); -var get = __webpack_require__(584); +var hasValues = __webpack_require__(589); +var get = __webpack_require__(581); module.exports = function(val, prop) { return hasValues(isObject(val) && prop ? get(val, prop) : val); @@ -68999,7 +68879,7 @@ module.exports = function(val, prop) { /***/ }), -/* 593 */ +/* 589 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69012,7 +68892,7 @@ module.exports = function(val, prop) { -var typeOf = __webpack_require__(594); +var typeOf = __webpack_require__(590); var isNumber = __webpack_require__(559); module.exports = function hasValue(val) { @@ -69066,7 +68946,7 @@ module.exports = function hasValue(val) { /***/ }), -/* 594 */ +/* 590 */ /***/ (function(module, exports, __webpack_require__) { var isBuffer = __webpack_require__(561); @@ -69191,7 +69071,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 595 */ +/* 591 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69205,9 +69085,9 @@ module.exports = function kindOf(val) { var split = __webpack_require__(554); -var extend = __webpack_require__(586); +var extend = __webpack_require__(550); var isPlainObject = __webpack_require__(544); -var isObject = __webpack_require__(582); +var isObject = __webpack_require__(551); module.exports = function(obj, prop, val) { if (!isObject(obj)) { @@ -69253,14 +69133,14 @@ function isValidKey(key) { /***/ }), -/* 596 */ +/* 592 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(597); -var forIn = __webpack_require__(598); +var isExtendable = __webpack_require__(593); +var forIn = __webpack_require__(594); function mixinDeep(target, objects) { var len = arguments.length, i = 0; @@ -69324,7 +69204,7 @@ module.exports = mixinDeep; /***/ }), -/* 597 */ +/* 593 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69345,7 +69225,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 598 */ +/* 594 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69368,7 +69248,7 @@ module.exports = function forIn(obj, fn, thisArg) { /***/ }), -/* 599 */ +/* 595 */ /***/ (function(module, exports) { /*! @@ -69395,14 +69275,14 @@ module.exports = pascalcase; /***/ }), -/* 600 */ +/* 596 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var util = __webpack_require__(112); -var utils = __webpack_require__(601); +var utils = __webpack_require__(597); /** * Expose class utils @@ -69767,7 +69647,7 @@ cu.bubble = function(Parent, events) { /***/ }), -/* 601 */ +/* 597 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69781,10 +69661,10 @@ var utils = {}; * Lazily required module dependencies */ -utils.union = __webpack_require__(583); -utils.define = __webpack_require__(602); +utils.union = __webpack_require__(580); +utils.define = __webpack_require__(598); utils.isObj = __webpack_require__(535); -utils.staticExtend = __webpack_require__(609); +utils.staticExtend = __webpack_require__(605); /** @@ -69795,7 +69675,7 @@ module.exports = utils; /***/ }), -/* 602 */ +/* 598 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69808,7 +69688,7 @@ module.exports = utils; -var isDescriptor = __webpack_require__(603); +var isDescriptor = __webpack_require__(599); module.exports = function defineProperty(obj, prop, val) { if (typeof obj !== 'object' && typeof obj !== 'function') { @@ -69833,7 +69713,7 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 603 */ +/* 599 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -69846,9 +69726,9 @@ module.exports = function defineProperty(obj, prop, val) { -var typeOf = __webpack_require__(604); -var isAccessor = __webpack_require__(605); -var isData = __webpack_require__(607); +var typeOf = __webpack_require__(600); +var isAccessor = __webpack_require__(601); +var isData = __webpack_require__(603); module.exports = function isDescriptor(obj, key) { if (typeOf(obj) !== 'object') { @@ -69862,7 +69742,7 @@ module.exports = function isDescriptor(obj, key) { /***/ }), -/* 604 */ +/* 600 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -70015,7 +69895,7 @@ function isBuffer(val) { /***/ }), -/* 605 */ +/* 601 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70028,7 +69908,7 @@ function isBuffer(val) { -var typeOf = __webpack_require__(606); +var typeOf = __webpack_require__(602); // accessor descriptor properties var accessor = { @@ -70091,7 +69971,7 @@ module.exports = isAccessorDescriptor; /***/ }), -/* 606 */ +/* 602 */ /***/ (function(module, exports, __webpack_require__) { var isBuffer = __webpack_require__(561); @@ -70213,7 +70093,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 607 */ +/* 603 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70226,7 +70106,7 @@ module.exports = function kindOf(val) { -var typeOf = __webpack_require__(608); +var typeOf = __webpack_require__(604); // data descriptor properties var data = { @@ -70275,7 +70155,7 @@ module.exports = isDataDescriptor; /***/ }), -/* 608 */ +/* 604 */ /***/ (function(module, exports, __webpack_require__) { var isBuffer = __webpack_require__(561); @@ -70397,7 +70277,7 @@ module.exports = function kindOf(val) { /***/ }), -/* 609 */ +/* 605 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70410,8 +70290,8 @@ module.exports = function kindOf(val) { -var copy = __webpack_require__(610); -var define = __webpack_require__(602); +var copy = __webpack_require__(606); +var define = __webpack_require__(598); var util = __webpack_require__(112); /** @@ -70494,15 +70374,15 @@ module.exports = extend; /***/ }), -/* 610 */ +/* 606 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var typeOf = __webpack_require__(560); -var copyDescriptor = __webpack_require__(611); -var define = __webpack_require__(602); +var copyDescriptor = __webpack_require__(607); +var define = __webpack_require__(598); /** * Copy static properties, prototype properties, and descriptors from one object to another. @@ -70675,7 +70555,7 @@ module.exports.has = has; /***/ }), -/* 611 */ +/* 607 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70763,16 +70643,16 @@ function isObject(val) { /***/ }), -/* 612 */ +/* 608 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(613); -var define = __webpack_require__(602); -var debug = __webpack_require__(615)('snapdragon:compiler'); -var utils = __webpack_require__(621); +var use = __webpack_require__(609); +var define = __webpack_require__(598); +var debug = __webpack_require__(611)('snapdragon:compiler'); +var utils = __webpack_require__(617); /** * Create a new `Compiler` with the given `options`. @@ -70926,7 +70806,7 @@ Compiler.prototype = { // source map support if (opts.sourcemap) { - var sourcemaps = __webpack_require__(640); + var sourcemaps = __webpack_require__(636); sourcemaps(this); this.mapVisit(this.ast.nodes); this.applySourceMaps(); @@ -70947,7 +70827,7 @@ module.exports = Compiler; /***/ }), -/* 613 */ +/* 609 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -70960,7 +70840,7 @@ module.exports = Compiler; -var utils = __webpack_require__(614); +var utils = __webpack_require__(610); module.exports = function base(app, opts) { if (!utils.isObject(app) && typeof app !== 'function') { @@ -71075,7 +70955,7 @@ module.exports = function base(app, opts) { /***/ }), -/* 614 */ +/* 610 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71089,7 +70969,7 @@ var utils = {}; * Lazily required module dependencies */ -utils.define = __webpack_require__(602); +utils.define = __webpack_require__(598); utils.isObject = __webpack_require__(535); @@ -71105,7 +70985,7 @@ module.exports = utils; /***/ }), -/* 615 */ +/* 611 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -71114,14 +70994,14 @@ module.exports = utils; */ if (typeof process !== 'undefined' && process.type === 'renderer') { - module.exports = __webpack_require__(616); + module.exports = __webpack_require__(612); } else { - module.exports = __webpack_require__(619); + module.exports = __webpack_require__(615); } /***/ }), -/* 616 */ +/* 612 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -71130,7 +71010,7 @@ if (typeof process !== 'undefined' && process.type === 'renderer') { * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(617); +exports = module.exports = __webpack_require__(613); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; @@ -71312,7 +71192,7 @@ function localstorage() { /***/ }), -/* 617 */ +/* 613 */ /***/ (function(module, exports, __webpack_require__) { @@ -71328,7 +71208,7 @@ exports.coerce = coerce; exports.disable = disable; exports.enable = enable; exports.enabled = enabled; -exports.humanize = __webpack_require__(618); +exports.humanize = __webpack_require__(614); /** * The currently active debug mode names, and names to skip. @@ -71520,7 +71400,7 @@ function coerce(val) { /***/ }), -/* 618 */ +/* 614 */ /***/ (function(module, exports) { /** @@ -71678,7 +71558,7 @@ function plural(ms, n, name) { /***/ }), -/* 619 */ +/* 615 */ /***/ (function(module, exports, __webpack_require__) { /** @@ -71694,7 +71574,7 @@ var util = __webpack_require__(112); * Expose `debug()` as the module. */ -exports = module.exports = __webpack_require__(617); +exports = module.exports = __webpack_require__(613); exports.init = init; exports.log = log; exports.formatArgs = formatArgs; @@ -71873,7 +71753,7 @@ function createWritableStdioStream (fd) { case 'PIPE': case 'TCP': - var net = __webpack_require__(620); + var net = __webpack_require__(616); stream = new net.Socket({ fd: fd, readable: false, @@ -71932,13 +71812,13 @@ exports.enable(load()); /***/ }), -/* 620 */ +/* 616 */ /***/ (function(module, exports) { module.exports = require("net"); /***/ }), -/* 621 */ +/* 617 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -71948,9 +71828,9 @@ module.exports = require("net"); * Module dependencies */ -exports.extend = __webpack_require__(586); -exports.SourceMap = __webpack_require__(622); -exports.sourceMapResolve = __webpack_require__(633); +exports.extend = __webpack_require__(550); +exports.SourceMap = __webpack_require__(618); +exports.sourceMapResolve = __webpack_require__(629); /** * Convert backslash in the given string to forward slashes @@ -71993,7 +71873,7 @@ exports.last = function(arr, n) { /***/ }), -/* 622 */ +/* 618 */ /***/ (function(module, exports, __webpack_require__) { /* @@ -72001,13 +71881,13 @@ exports.last = function(arr, n) { * Licensed under the New BSD license. See LICENSE.txt or: * http://opensource.org/licenses/BSD-3-Clause */ -exports.SourceMapGenerator = __webpack_require__(623).SourceMapGenerator; -exports.SourceMapConsumer = __webpack_require__(629).SourceMapConsumer; -exports.SourceNode = __webpack_require__(632).SourceNode; +exports.SourceMapGenerator = __webpack_require__(619).SourceMapGenerator; +exports.SourceMapConsumer = __webpack_require__(625).SourceMapConsumer; +exports.SourceNode = __webpack_require__(628).SourceNode; /***/ }), -/* 623 */ +/* 619 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72017,10 +71897,10 @@ exports.SourceNode = __webpack_require__(632).SourceNode; * http://opensource.org/licenses/BSD-3-Clause */ -var base64VLQ = __webpack_require__(624); -var util = __webpack_require__(626); -var ArraySet = __webpack_require__(627).ArraySet; -var MappingList = __webpack_require__(628).MappingList; +var base64VLQ = __webpack_require__(620); +var util = __webpack_require__(622); +var ArraySet = __webpack_require__(623).ArraySet; +var MappingList = __webpack_require__(624).MappingList; /** * An instance of the SourceMapGenerator represents a source map which is @@ -72429,7 +72309,7 @@ exports.SourceMapGenerator = SourceMapGenerator; /***/ }), -/* 624 */ +/* 620 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72469,7 +72349,7 @@ exports.SourceMapGenerator = SourceMapGenerator; * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -var base64 = __webpack_require__(625); +var base64 = __webpack_require__(621); // A single base 64 digit can contain 6 bits of data. For the base 64 variable // length quantities we use in the source map spec, the first bit is the sign, @@ -72575,7 +72455,7 @@ exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { /***/ }), -/* 625 */ +/* 621 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -72648,7 +72528,7 @@ exports.decode = function (charCode) { /***/ }), -/* 626 */ +/* 622 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73071,7 +72951,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate /***/ }), -/* 627 */ +/* 623 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73081,7 +72961,7 @@ exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflate * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(626); +var util = __webpack_require__(622); var has = Object.prototype.hasOwnProperty; var hasNativeMap = typeof Map !== "undefined"; @@ -73198,7 +73078,7 @@ exports.ArraySet = ArraySet; /***/ }), -/* 628 */ +/* 624 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73208,7 +73088,7 @@ exports.ArraySet = ArraySet; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(626); +var util = __webpack_require__(622); /** * Determine whether mappingB is after mappingA with respect to generated @@ -73283,7 +73163,7 @@ exports.MappingList = MappingList; /***/ }), -/* 629 */ +/* 625 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -73293,11 +73173,11 @@ exports.MappingList = MappingList; * http://opensource.org/licenses/BSD-3-Clause */ -var util = __webpack_require__(626); -var binarySearch = __webpack_require__(630); -var ArraySet = __webpack_require__(627).ArraySet; -var base64VLQ = __webpack_require__(624); -var quickSort = __webpack_require__(631).quickSort; +var util = __webpack_require__(622); +var binarySearch = __webpack_require__(626); +var ArraySet = __webpack_require__(623).ArraySet; +var base64VLQ = __webpack_require__(620); +var quickSort = __webpack_require__(627).quickSort; function SourceMapConsumer(aSourceMap) { var sourceMap = aSourceMap; @@ -74371,7 +74251,7 @@ exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer; /***/ }), -/* 630 */ +/* 626 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74488,7 +74368,7 @@ exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { /***/ }), -/* 631 */ +/* 627 */ /***/ (function(module, exports) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74608,7 +74488,7 @@ exports.quickSort = function (ary, comparator) { /***/ }), -/* 632 */ +/* 628 */ /***/ (function(module, exports, __webpack_require__) { /* -*- Mode: js; js-indent-level: 2; -*- */ @@ -74618,8 +74498,8 @@ exports.quickSort = function (ary, comparator) { * http://opensource.org/licenses/BSD-3-Clause */ -var SourceMapGenerator = __webpack_require__(623).SourceMapGenerator; -var util = __webpack_require__(626); +var SourceMapGenerator = __webpack_require__(619).SourceMapGenerator; +var util = __webpack_require__(622); // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other // operating systems these days (capturing the result). @@ -75027,17 +74907,17 @@ exports.SourceNode = SourceNode; /***/ }), -/* 633 */ +/* 629 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014, 2015, 2016, 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var sourceMappingURL = __webpack_require__(634) -var resolveUrl = __webpack_require__(635) -var decodeUriComponent = __webpack_require__(636) -var urix = __webpack_require__(638) -var atob = __webpack_require__(639) +var sourceMappingURL = __webpack_require__(630) +var resolveUrl = __webpack_require__(631) +var decodeUriComponent = __webpack_require__(632) +var urix = __webpack_require__(634) +var atob = __webpack_require__(635) @@ -75335,7 +75215,7 @@ module.exports = { /***/ }), -/* 634 */ +/* 630 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;// Copyright 2014 Simon Lydell @@ -75398,7 +75278,7 @@ void (function(root, factory) { /***/ }), -/* 635 */ +/* 631 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -75416,13 +75296,13 @@ module.exports = resolveUrl /***/ }), -/* 636 */ +/* 632 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2017 Simon Lydell // X11 (“MIT”) Licensed. (See LICENSE.) -var decodeUriComponent = __webpack_require__(637) +var decodeUriComponent = __webpack_require__(633) function customDecodeUriComponent(string) { // `decodeUriComponent` turns `+` into ` `, but that's not wanted. @@ -75433,7 +75313,7 @@ module.exports = customDecodeUriComponent /***/ }), -/* 637 */ +/* 633 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75534,7 +75414,7 @@ module.exports = function (encodedURI) { /***/ }), -/* 638 */ +/* 634 */ /***/ (function(module, exports, __webpack_require__) { // Copyright 2014 Simon Lydell @@ -75557,7 +75437,7 @@ module.exports = urix /***/ }), -/* 639 */ +/* 635 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75571,7 +75451,7 @@ module.exports = atob.atob = atob; /***/ }), -/* 640 */ +/* 636 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -75579,8 +75459,8 @@ module.exports = atob.atob = atob; var fs = __webpack_require__(134); var path = __webpack_require__(4); -var define = __webpack_require__(602); -var utils = __webpack_require__(621); +var define = __webpack_require__(598); +var utils = __webpack_require__(617); /** * Expose `mixin()`. @@ -75723,19 +75603,19 @@ exports.comment = function(node) { /***/ }), -/* 641 */ +/* 637 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var use = __webpack_require__(613); +var use = __webpack_require__(609); var util = __webpack_require__(112); -var Cache = __webpack_require__(642); -var define = __webpack_require__(602); -var debug = __webpack_require__(615)('snapdragon:parser'); -var Position = __webpack_require__(643); -var utils = __webpack_require__(621); +var Cache = __webpack_require__(638); +var define = __webpack_require__(598); +var debug = __webpack_require__(611)('snapdragon:parser'); +var Position = __webpack_require__(639); +var utils = __webpack_require__(617); /** * Create a new `Parser` with the given `input` and `options`. @@ -76263,7 +76143,7 @@ module.exports = Parser; /***/ }), -/* 642 */ +/* 638 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76370,13 +76250,13 @@ MapCache.prototype.del = function mapDelete(key) { /***/ }), -/* 643 */ +/* 639 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var define = __webpack_require__(602); +var define = __webpack_require__(598); /** * Store position for a node @@ -76391,13 +76271,13 @@ module.exports = function Position(start, parser) { /***/ }), -/* 644 */ +/* 640 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(645); +var isExtendable = __webpack_require__(641); var assignSymbols = __webpack_require__(545); module.exports = Object.assign || function(obj/*, objects*/) { @@ -76458,7 +76338,7 @@ function isEnum(obj, key) { /***/ }), -/* 645 */ +/* 641 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76479,14 +76359,14 @@ module.exports = function isExtendable(val) { /***/ }), -/* 646 */ +/* 642 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var nanomatch = __webpack_require__(647); -var extglob = __webpack_require__(662); +var nanomatch = __webpack_require__(643); +var extglob = __webpack_require__(658); module.exports = function(snapdragon) { var compilers = snapdragon.compiler.compilers; @@ -76563,7 +76443,7 @@ function escapeExtglobs(compiler) { /***/ }), -/* 647 */ +/* 643 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -76575,16 +76455,16 @@ function escapeExtglobs(compiler) { var util = __webpack_require__(112); var toRegex = __webpack_require__(527); -var extend = __webpack_require__(648); +var extend = __webpack_require__(644); /** * Local dependencies */ -var compilers = __webpack_require__(650); -var parsers = __webpack_require__(651); -var cache = __webpack_require__(654); -var utils = __webpack_require__(656); +var compilers = __webpack_require__(646); +var parsers = __webpack_require__(647); +var cache = __webpack_require__(650); +var utils = __webpack_require__(652); var MAX_LENGTH = 1024 * 64; /** @@ -77408,13 +77288,13 @@ module.exports = nanomatch; /***/ }), -/* 648 */ +/* 644 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var isExtendable = __webpack_require__(649); +var isExtendable = __webpack_require__(645); var assignSymbols = __webpack_require__(545); module.exports = Object.assign || function(obj/*, objects*/) { @@ -77475,7 +77355,7 @@ function isEnum(obj, key) { /***/ }), -/* 649 */ +/* 645 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77496,7 +77376,7 @@ module.exports = function isExtendable(val) { /***/ }), -/* 650 */ +/* 646 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77842,7 +77722,7 @@ module.exports = function(nanomatch, options) { /***/ }), -/* 651 */ +/* 647 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -77850,7 +77730,7 @@ module.exports = function(nanomatch, options) { var regexNot = __webpack_require__(546); var toRegex = __webpack_require__(527); -var isOdd = __webpack_require__(652); +var isOdd = __webpack_require__(648); /** * Characters to use in negation regex (we want to "not" match @@ -78236,7 +78116,7 @@ module.exports.not = NOT_REGEX; /***/ }), -/* 652 */ +/* 648 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78249,7 +78129,7 @@ module.exports.not = NOT_REGEX; -var isNumber = __webpack_require__(653); +var isNumber = __webpack_require__(649); module.exports = function isOdd(i) { if (!isNumber(i)) { @@ -78263,7 +78143,7 @@ module.exports = function isOdd(i) { /***/ }), -/* 653 */ +/* 649 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78291,14 +78171,14 @@ module.exports = function isNumber(num) { /***/ }), -/* 654 */ +/* 650 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(655))(); +module.exports = new (__webpack_require__(651))(); /***/ }), -/* 655 */ +/* 651 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78311,7 +78191,7 @@ module.exports = new (__webpack_require__(655))(); -var MapCache = __webpack_require__(642); +var MapCache = __webpack_require__(638); /** * Create a new `FragmentCache` with an optional object to use for `caches`. @@ -78433,7 +78313,7 @@ exports = module.exports = FragmentCache; /***/ }), -/* 656 */ +/* 652 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78446,13 +78326,13 @@ var path = __webpack_require__(4); * Module dependencies */ -var isWindows = __webpack_require__(657)(); -var Snapdragon = __webpack_require__(572); -utils.define = __webpack_require__(658); -utils.diff = __webpack_require__(659); -utils.extend = __webpack_require__(648); -utils.pick = __webpack_require__(660); -utils.typeOf = __webpack_require__(661); +var isWindows = __webpack_require__(653)(); +var Snapdragon = __webpack_require__(570); +utils.define = __webpack_require__(654); +utils.diff = __webpack_require__(655); +utils.extend = __webpack_require__(644); +utils.pick = __webpack_require__(656); +utils.typeOf = __webpack_require__(657); utils.unique = __webpack_require__(549); /** @@ -78819,7 +78699,7 @@ utils.unixify = function(options) { /***/ }), -/* 657 */ +/* 653 */ /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! @@ -78847,7 +78727,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ /***/ }), -/* 658 */ +/* 654 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78892,7 +78772,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 659 */ +/* 655 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78946,7 +78826,7 @@ function diffArray(one, two) { /***/ }), -/* 660 */ +/* 656 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -78988,7 +78868,7 @@ module.exports = function pick(obj, keys) { /***/ }), -/* 661 */ +/* 657 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -79123,7 +79003,7 @@ function isBuffer(val) { /***/ }), -/* 662 */ +/* 658 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79133,7 +79013,7 @@ function isBuffer(val) { * Module dependencies */ -var extend = __webpack_require__(586); +var extend = __webpack_require__(550); var unique = __webpack_require__(549); var toRegex = __webpack_require__(527); @@ -79141,10 +79021,10 @@ var toRegex = __webpack_require__(527); * Local dependencies */ -var compilers = __webpack_require__(663); -var parsers = __webpack_require__(669); -var Extglob = __webpack_require__(672); -var utils = __webpack_require__(671); +var compilers = __webpack_require__(659); +var parsers = __webpack_require__(665); +var Extglob = __webpack_require__(668); +var utils = __webpack_require__(667); var MAX_LENGTH = 1024 * 64; /** @@ -79461,13 +79341,13 @@ module.exports = extglob; /***/ }), -/* 663 */ +/* 659 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(664); +var brackets = __webpack_require__(660); /** * Extglob compilers @@ -79637,7 +79517,7 @@ module.exports = function(extglob) { /***/ }), -/* 664 */ +/* 660 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79647,16 +79527,16 @@ module.exports = function(extglob) { * Local dependencies */ -var compilers = __webpack_require__(665); -var parsers = __webpack_require__(667); +var compilers = __webpack_require__(661); +var parsers = __webpack_require__(663); /** * Module dependencies */ -var debug = __webpack_require__(615)('expand-brackets'); -var extend = __webpack_require__(586); -var Snapdragon = __webpack_require__(572); +var debug = __webpack_require__(611)('expand-brackets'); +var extend = __webpack_require__(550); +var Snapdragon = __webpack_require__(570); var toRegex = __webpack_require__(527); /** @@ -79855,13 +79735,13 @@ module.exports = brackets; /***/ }), -/* 665 */ +/* 661 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var posix = __webpack_require__(666); +var posix = __webpack_require__(662); module.exports = function(brackets) { brackets.compiler @@ -79949,7 +79829,7 @@ module.exports = function(brackets) { /***/ }), -/* 666 */ +/* 662 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -79978,14 +79858,14 @@ module.exports = { /***/ }), -/* 667 */ +/* 663 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(668); -var define = __webpack_require__(602); +var utils = __webpack_require__(664); +var define = __webpack_require__(598); /** * Text regex @@ -80204,7 +80084,7 @@ module.exports.TEXT_REGEX = TEXT_REGEX; /***/ }), -/* 668 */ +/* 664 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80245,15 +80125,15 @@ exports.createRegex = function(pattern, include) { /***/ }), -/* 669 */ +/* 665 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var brackets = __webpack_require__(664); -var define = __webpack_require__(670); -var utils = __webpack_require__(671); +var brackets = __webpack_require__(660); +var define = __webpack_require__(666); +var utils = __webpack_require__(667); /** * Characters to use in text regex (we want to "not" match @@ -80408,7 +80288,7 @@ module.exports = parsers; /***/ }), -/* 670 */ +/* 666 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80446,14 +80326,14 @@ module.exports = function defineProperty(obj, prop, val) { /***/ }), -/* 671 */ +/* 667 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var regex = __webpack_require__(546); -var Cache = __webpack_require__(655); +var Cache = __webpack_require__(651); /** * Utils @@ -80522,7 +80402,7 @@ utils.createRegex = function(str) { /***/ }), -/* 672 */ +/* 668 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80532,16 +80412,16 @@ utils.createRegex = function(str) { * Module dependencies */ -var Snapdragon = __webpack_require__(572); -var define = __webpack_require__(670); -var extend = __webpack_require__(586); +var Snapdragon = __webpack_require__(570); +var define = __webpack_require__(666); +var extend = __webpack_require__(550); /** * Local dependencies */ -var compilers = __webpack_require__(663); -var parsers = __webpack_require__(669); +var compilers = __webpack_require__(659); +var parsers = __webpack_require__(665); /** * Customize Snapdragon parser and renderer @@ -80607,14 +80487,14 @@ module.exports = Extglob; /***/ }), -/* 673 */ +/* 669 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var extglob = __webpack_require__(662); -var nanomatch = __webpack_require__(647); +var extglob = __webpack_require__(658); +var nanomatch = __webpack_require__(643); var regexNot = __webpack_require__(546); var toRegex = __webpack_require__(527); var not; @@ -80697,14 +80577,14 @@ function textRegex(pattern) { /***/ }), -/* 674 */ +/* 670 */ /***/ (function(module, exports, __webpack_require__) { -module.exports = new (__webpack_require__(655))(); +module.exports = new (__webpack_require__(651))(); /***/ }), -/* 675 */ +/* 671 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -80717,12 +80597,12 @@ var path = __webpack_require__(4); * Module dependencies */ -var Snapdragon = __webpack_require__(572); -utils.define = __webpack_require__(676); -utils.diff = __webpack_require__(659); -utils.extend = __webpack_require__(644); -utils.pick = __webpack_require__(660); -utils.typeOf = __webpack_require__(677); +var Snapdragon = __webpack_require__(570); +utils.define = __webpack_require__(672); +utils.diff = __webpack_require__(655); +utils.extend = __webpack_require__(640); +utils.pick = __webpack_require__(656); +utils.typeOf = __webpack_require__(673); utils.unique = __webpack_require__(549); /** @@ -81020,7 +80900,7 @@ utils.unixify = function(options) { /***/ }), -/* 676 */ +/* 672 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81065,7 +80945,7 @@ module.exports = function defineProperty(obj, key, val) { /***/ }), -/* 677 */ +/* 673 */ /***/ (function(module, exports) { var toString = Object.prototype.toString; @@ -81200,7 +81080,7 @@ function isBuffer(val) { /***/ }), -/* 678 */ +/* 674 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81219,9 +81099,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(679); -var reader_1 = __webpack_require__(692); -var fs_stream_1 = __webpack_require__(696); +var readdir = __webpack_require__(675); +var reader_1 = __webpack_require__(688); +var fs_stream_1 = __webpack_require__(692); var ReaderAsync = /** @class */ (function (_super) { __extends(ReaderAsync, _super); function ReaderAsync() { @@ -81282,15 +81162,15 @@ exports.default = ReaderAsync; /***/ }), -/* 679 */ +/* 675 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const readdirSync = __webpack_require__(680); -const readdirAsync = __webpack_require__(688); -const readdirStream = __webpack_require__(691); +const readdirSync = __webpack_require__(676); +const readdirAsync = __webpack_require__(684); +const readdirStream = __webpack_require__(687); module.exports = exports = readdirAsyncPath; exports.readdir = exports.readdirAsync = exports.async = readdirAsyncPath; @@ -81374,7 +81254,7 @@ function readdirStreamStat (dir, options) { /***/ }), -/* 680 */ +/* 676 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81382,11 +81262,11 @@ function readdirStreamStat (dir, options) { module.exports = readdirSync; -const DirectoryReader = __webpack_require__(681); +const DirectoryReader = __webpack_require__(677); let syncFacade = { - fs: __webpack_require__(686), - forEach: __webpack_require__(687), + fs: __webpack_require__(682), + forEach: __webpack_require__(683), sync: true }; @@ -81415,7 +81295,7 @@ function readdirSync (dir, options, internalOptions) { /***/ }), -/* 681 */ +/* 677 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -81424,9 +81304,9 @@ function readdirSync (dir, options, internalOptions) { const Readable = __webpack_require__(138).Readable; const EventEmitter = __webpack_require__(156).EventEmitter; const path = __webpack_require__(4); -const normalizeOptions = __webpack_require__(682); -const stat = __webpack_require__(684); -const call = __webpack_require__(685); +const normalizeOptions = __webpack_require__(678); +const stat = __webpack_require__(680); +const call = __webpack_require__(681); /** * Asynchronously reads the contents of a directory and streams the results @@ -81802,14 +81682,14 @@ module.exports = DirectoryReader; /***/ }), -/* 682 */ +/* 678 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const globToRegExp = __webpack_require__(683); +const globToRegExp = __webpack_require__(679); module.exports = normalizeOptions; @@ -81986,7 +81866,7 @@ function normalizeOptions (options, internalOptions) { /***/ }), -/* 683 */ +/* 679 */ /***/ (function(module, exports) { module.exports = function (glob, opts) { @@ -82123,13 +82003,13 @@ module.exports = function (glob, opts) { /***/ }), -/* 684 */ +/* 680 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const call = __webpack_require__(685); +const call = __webpack_require__(681); module.exports = stat; @@ -82204,7 +82084,7 @@ function symlinkStat (fs, path, lstats, callback) { /***/ }), -/* 685 */ +/* 681 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82265,14 +82145,14 @@ function callOnce (fn) { /***/ }), -/* 686 */ +/* 682 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); -const call = __webpack_require__(685); +const call = __webpack_require__(681); /** * A facade around {@link fs.readdirSync} that allows it to be called @@ -82336,7 +82216,7 @@ exports.lstat = function (path, callback) { /***/ }), -/* 687 */ +/* 683 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82365,7 +82245,7 @@ function syncForEach (array, iterator, done) { /***/ }), -/* 688 */ +/* 684 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82373,12 +82253,12 @@ function syncForEach (array, iterator, done) { module.exports = readdirAsync; -const maybe = __webpack_require__(689); -const DirectoryReader = __webpack_require__(681); +const maybe = __webpack_require__(685); +const DirectoryReader = __webpack_require__(677); let asyncFacade = { fs: __webpack_require__(134), - forEach: __webpack_require__(690), + forEach: __webpack_require__(686), async: true }; @@ -82420,7 +82300,7 @@ function readdirAsync (dir, options, callback, internalOptions) { /***/ }), -/* 689 */ +/* 685 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82447,7 +82327,7 @@ module.exports = function maybe (cb, promise) { /***/ }), -/* 690 */ +/* 686 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82483,7 +82363,7 @@ function asyncForEach (array, iterator, done) { /***/ }), -/* 691 */ +/* 687 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82491,11 +82371,11 @@ function asyncForEach (array, iterator, done) { module.exports = readdirStream; -const DirectoryReader = __webpack_require__(681); +const DirectoryReader = __webpack_require__(677); let streamFacade = { fs: __webpack_require__(134), - forEach: __webpack_require__(690), + forEach: __webpack_require__(686), async: true }; @@ -82515,16 +82395,16 @@ function readdirStream (dir, options, internalOptions) { /***/ }), -/* 692 */ +/* 688 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = __webpack_require__(4); -var deep_1 = __webpack_require__(693); -var entry_1 = __webpack_require__(695); -var pathUtil = __webpack_require__(694); +var deep_1 = __webpack_require__(689); +var entry_1 = __webpack_require__(691); +var pathUtil = __webpack_require__(690); var Reader = /** @class */ (function () { function Reader(options) { this.options = options; @@ -82590,13 +82470,13 @@ exports.default = Reader; /***/ }), -/* 693 */ +/* 689 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(694); +var pathUtils = __webpack_require__(690); var patternUtils = __webpack_require__(521); var DeepFilter = /** @class */ (function () { function DeepFilter(options, micromatchOptions) { @@ -82680,7 +82560,7 @@ exports.default = DeepFilter; /***/ }), -/* 694 */ +/* 690 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82711,13 +82591,13 @@ exports.makeAbsolute = makeAbsolute; /***/ }), -/* 695 */ +/* 691 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -var pathUtils = __webpack_require__(694); +var pathUtils = __webpack_require__(690); var patternUtils = __webpack_require__(521); var EntryFilter = /** @class */ (function () { function EntryFilter(options, micromatchOptions) { @@ -82803,7 +82683,7 @@ exports.default = EntryFilter; /***/ }), -/* 696 */ +/* 692 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82823,8 +82703,8 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(138); -var fsStat = __webpack_require__(697); -var fs_1 = __webpack_require__(701); +var fsStat = __webpack_require__(693); +var fs_1 = __webpack_require__(697); var FileSystemStream = /** @class */ (function (_super) { __extends(FileSystemStream, _super); function FileSystemStream() { @@ -82874,14 +82754,14 @@ exports.default = FileSystemStream; /***/ }), -/* 697 */ +/* 693 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const optionsManager = __webpack_require__(698); -const statProvider = __webpack_require__(700); +const optionsManager = __webpack_require__(694); +const statProvider = __webpack_require__(696); /** * Asynchronous API. */ @@ -82912,13 +82792,13 @@ exports.statSync = statSync; /***/ }), -/* 698 */ +/* 694 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const fsAdapter = __webpack_require__(699); +const fsAdapter = __webpack_require__(695); function prepare(opts) { const options = Object.assign({ fs: fsAdapter.getFileSystemAdapter(opts ? opts.fs : undefined), @@ -82931,7 +82811,7 @@ exports.prepare = prepare; /***/ }), -/* 699 */ +/* 695 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -82954,7 +82834,7 @@ exports.getFileSystemAdapter = getFileSystemAdapter; /***/ }), -/* 700 */ +/* 696 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83006,7 +82886,7 @@ exports.isFollowedSymlink = isFollowedSymlink; /***/ }), -/* 701 */ +/* 697 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83037,7 +82917,7 @@ exports.default = FileSystem; /***/ }), -/* 702 */ +/* 698 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83057,9 +82937,9 @@ var __extends = (this && this.__extends) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); var stream = __webpack_require__(138); -var readdir = __webpack_require__(679); -var reader_1 = __webpack_require__(692); -var fs_stream_1 = __webpack_require__(696); +var readdir = __webpack_require__(675); +var reader_1 = __webpack_require__(688); +var fs_stream_1 = __webpack_require__(692); var TransformStream = /** @class */ (function (_super) { __extends(TransformStream, _super); function TransformStream(reader) { @@ -83127,7 +83007,7 @@ exports.default = ReaderStream; /***/ }), -/* 703 */ +/* 699 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83146,9 +83026,9 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var readdir = __webpack_require__(679); -var reader_1 = __webpack_require__(692); -var fs_sync_1 = __webpack_require__(704); +var readdir = __webpack_require__(675); +var reader_1 = __webpack_require__(688); +var fs_sync_1 = __webpack_require__(700); var ReaderSync = /** @class */ (function (_super) { __extends(ReaderSync, _super); function ReaderSync() { @@ -83208,7 +83088,7 @@ exports.default = ReaderSync; /***/ }), -/* 704 */ +/* 700 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83227,8 +83107,8 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -var fsStat = __webpack_require__(697); -var fs_1 = __webpack_require__(701); +var fsStat = __webpack_require__(693); +var fs_1 = __webpack_require__(697); var FileSystemSync = /** @class */ (function (_super) { __extends(FileSystemSync, _super); function FileSystemSync() { @@ -83274,7 +83154,7 @@ exports.default = FileSystemSync; /***/ }), -/* 705 */ +/* 701 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83290,7 +83170,7 @@ exports.flatten = flatten; /***/ }), -/* 706 */ +/* 702 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83311,13 +83191,13 @@ exports.merge = merge; /***/ }), -/* 707 */ +/* 703 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); -const pathType = __webpack_require__(708); +const pathType = __webpack_require__(704); const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0]; @@ -83383,13 +83263,13 @@ module.exports.sync = (input, opts) => { /***/ }), -/* 708 */ +/* 704 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const fs = __webpack_require__(134); -const pify = __webpack_require__(709); +const pify = __webpack_require__(705); function type(fn, fn2, fp) { if (typeof fp !== 'string') { @@ -83432,7 +83312,7 @@ exports.symlinkSync = typeSync.bind(null, 'lstatSync', 'isSymbolicLink'); /***/ }), -/* 709 */ +/* 705 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83523,7 +83403,7 @@ module.exports = (obj, opts) => { /***/ }), -/* 710 */ +/* 706 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -83531,9 +83411,9 @@ module.exports = (obj, opts) => { const fs = __webpack_require__(134); const path = __webpack_require__(4); const fastGlob = __webpack_require__(517); -const gitIgnore = __webpack_require__(711); -const pify = __webpack_require__(712); -const slash = __webpack_require__(713); +const gitIgnore = __webpack_require__(707); +const pify = __webpack_require__(708); +const slash = __webpack_require__(709); const DEFAULT_IGNORE = [ '**/node_modules/**', @@ -83631,7 +83511,7 @@ module.exports.sync = options => { /***/ }), -/* 711 */ +/* 707 */ /***/ (function(module, exports) { // A simple implementation of make-array @@ -84100,7 +83980,7 @@ module.exports = options => new IgnoreBase(options) /***/ }), -/* 712 */ +/* 708 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84175,7 +84055,7 @@ module.exports = (input, options) => { /***/ }), -/* 713 */ +/* 709 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84193,7 +84073,7 @@ module.exports = input => { /***/ }), -/* 714 */ +/* 710 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84206,7 +84086,7 @@ module.exports = input => { -var isGlob = __webpack_require__(715); +var isGlob = __webpack_require__(711); module.exports = function hasGlob(val) { if (val == null) return false; @@ -84226,7 +84106,7 @@ module.exports = function hasGlob(val) { /***/ }), -/* 715 */ +/* 711 */ /***/ (function(module, exports, __webpack_require__) { /*! @@ -84257,17 +84137,17 @@ module.exports = function isGlob(str) { /***/ }), -/* 716 */ +/* 712 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const path = __webpack_require__(4); const {constants: fsConstants} = __webpack_require__(134); -const pEvent = __webpack_require__(717); -const CpFileError = __webpack_require__(720); -const fs = __webpack_require__(722); -const ProgressEmitter = __webpack_require__(725); +const pEvent = __webpack_require__(713); +const CpFileError = __webpack_require__(716); +const fs = __webpack_require__(718); +const ProgressEmitter = __webpack_require__(721); const cpFileAsync = async (source, destination, options, progressEmitter) => { let readError; @@ -84381,12 +84261,12 @@ module.exports.sync = (source, destination, options) => { /***/ }), -/* 717 */ +/* 713 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pTimeout = __webpack_require__(718); +const pTimeout = __webpack_require__(714); const symbolAsyncIterator = Symbol.asyncIterator || '@@asyncIterator'; @@ -84677,12 +84557,12 @@ module.exports.iterator = (emitter, event, options) => { /***/ }), -/* 718 */ +/* 714 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pFinally = __webpack_require__(719); +const pFinally = __webpack_require__(715); class TimeoutError extends Error { constructor(message) { @@ -84728,7 +84608,7 @@ module.exports.TimeoutError = TimeoutError; /***/ }), -/* 719 */ +/* 715 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84750,12 +84630,12 @@ module.exports = (promise, onFinally) => { /***/ }), -/* 720 */ +/* 716 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(721); +const NestedError = __webpack_require__(717); class CpFileError extends NestedError { constructor(message, nested) { @@ -84769,7 +84649,7 @@ module.exports = CpFileError; /***/ }), -/* 721 */ +/* 717 */ /***/ (function(module, exports, __webpack_require__) { var inherits = __webpack_require__(112).inherits; @@ -84825,16 +84705,16 @@ module.exports = NestedError; /***/ }), -/* 722 */ +/* 718 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; const {promisify} = __webpack_require__(112); const fs = __webpack_require__(133); -const makeDir = __webpack_require__(723); -const pEvent = __webpack_require__(717); -const CpFileError = __webpack_require__(720); +const makeDir = __webpack_require__(719); +const pEvent = __webpack_require__(713); +const CpFileError = __webpack_require__(716); const stat = promisify(fs.stat); const lstat = promisify(fs.lstat); @@ -84931,7 +84811,7 @@ exports.copyFileSync = (source, destination, flags) => { /***/ }), -/* 723 */ +/* 719 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -84939,7 +84819,7 @@ exports.copyFileSync = (source, destination, flags) => { const fs = __webpack_require__(134); const path = __webpack_require__(4); const {promisify} = __webpack_require__(112); -const semver = __webpack_require__(724); +const semver = __webpack_require__(720); const useNativeRecursiveOption = semver.satisfies(process.version, '>=10.12.0'); @@ -85094,7 +84974,7 @@ module.exports.sync = (input, options) => { /***/ }), -/* 724 */ +/* 720 */ /***/ (function(module, exports) { exports = module.exports = SemVer @@ -86696,7 +86576,7 @@ function coerce (version, options) { /***/ }), -/* 725 */ +/* 721 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86737,7 +86617,7 @@ module.exports = ProgressEmitter; /***/ }), -/* 726 */ +/* 722 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86783,12 +86663,12 @@ exports.default = module.exports; /***/ }), -/* 727 */ +/* 723 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const pMap = __webpack_require__(728); +const pMap = __webpack_require__(724); const pFilter = async (iterable, filterer, options) => { const values = await pMap( @@ -86805,7 +86685,7 @@ module.exports.default = pFilter; /***/ }), -/* 728 */ +/* 724 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -86884,12 +86764,12 @@ module.exports.default = pMap; /***/ }), -/* 729 */ +/* 725 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -const NestedError = __webpack_require__(721); +const NestedError = __webpack_require__(717); class CpyError extends NestedError { constructor(message, nested) { diff --git a/x-pack/plugins/reporting/server/lib/layouts/index.ts b/x-pack/plugins/reporting/server/lib/layouts/index.ts index e0b5b3f095443..b6804b6ac8c8a 100644 --- a/x-pack/plugins/reporting/server/lib/layouts/index.ts +++ b/x-pack/plugins/reporting/server/lib/layouts/index.ts @@ -7,7 +7,7 @@ import { LevelLogger } from '../'; import { LayoutSelectorDictionary, Size } from '../../../common/types'; import { HeadlessChromiumDriver } from '../../browsers'; -import { Layout } from './layout'; +import type { Layout } from './layout'; export { LayoutParams, @@ -17,7 +17,7 @@ export { Size, } from '../../../common/types'; export { createLayout } from './create_layout'; -export { Layout } from './layout'; +export type { Layout } from './layout'; export { PreserveLayout } from './preserve_layout'; export { CanvasLayout } from './canvas_layout'; export { PrintLayout } from './print_layout'; diff --git a/x-pack/plugins/reporting/server/lib/layouts/layout.ts b/x-pack/plugins/reporting/server/lib/layouts/layout.ts index cb068632063a5..027404f4c33e2 100644 --- a/x-pack/plugins/reporting/server/lib/layouts/layout.ts +++ b/x-pack/plugins/reporting/server/lib/layouts/layout.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CustomPageSize, PredefinedPageSize } from 'pdfmake/interfaces'; -import { PageSizeParams, PdfImageSize, Size } from './'; +import type { CustomPageSize, PredefinedPageSize } from 'pdfmake/interfaces'; +import type { PageSizeParams, PdfImageSize, Size } from '../../../common/types'; export interface ViewZoomWidthHeight { zoom: number; diff --git a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts index ccd08e01fec19..e7c84f2088319 100644 --- a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts +++ b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts @@ -9,7 +9,8 @@ import { CustomPageSize } from 'pdfmake/interfaces'; import { getDefaultLayoutSelectors } from '../../../common'; import { LAYOUT_TYPES } from '../../../common/constants'; import { LayoutSelectorDictionary, PageSizeParams, Size } from '../../../common/types'; -import { Layout, LayoutInstance } from './'; +import type { LayoutInstance } from './'; +import { Layout } from './layout'; // We use a zoom of two to bump up the resolution of the screenshot a bit. const ZOOM: number = 2; diff --git a/x-pack/plugins/reporting/server/lib/layouts/print_layout.ts b/x-pack/plugins/reporting/server/lib/layouts/print_layout.ts index 8db1fa7ff6347..c51582aa404d9 100644 --- a/x-pack/plugins/reporting/server/lib/layouts/print_layout.ts +++ b/x-pack/plugins/reporting/server/lib/layouts/print_layout.ts @@ -13,7 +13,8 @@ import { LAYOUT_TYPES } from '../../../common/constants'; import { LayoutSelectorDictionary, Size } from '../../../common/types'; import { HeadlessChromiumDriver } from '../../browsers'; import { CaptureConfig } from '../../types'; -import { Layout, LayoutInstance } from './'; +import type { LayoutInstance } from './'; +import { Layout } from './layout'; export class PrintLayout extends Layout implements LayoutInstance { public readonly selectors: LayoutSelectorDictionary = { diff --git a/yarn.lock b/yarn.lock index 7625510d3b915..174f1284a3a6b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@babel/cli@^7.10.5": - version "7.11.6" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.11.6.tgz#1fcbe61c2a6900c3539c06ee58901141f3558482" - integrity sha512-+w7BZCvkewSmaRM6H4L2QM3RL90teqEIHDIFXAmrW33+0jhlymnDAEdqVeCZATvxhQuio1ifoGVlJJbIiH9Ffg== +"@babel/cli@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.12.10.tgz#67a1015b1cd505bde1696196febf910c4c339a48" + integrity sha512-+y4ZnePpvWs1fc/LhZRTHkTesbXkyBYuOB+5CyodZqrEuETXi3zOVfpAQIdgC3lXbHLTDG9dQosxR9BhvLKDLQ== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -16,7 +16,8 @@ slash "^2.0.0" source-map "^0.5.0" optionalDependencies: - chokidar "^2.1.8" + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents" + chokidar "^3.4.0" "@babel/code-frame@7.8.3": version "7.8.3" @@ -32,6 +33,13 @@ dependencies: "@babel/highlight" "^7.10.4" +"@babel/code-frame@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" @@ -41,6 +49,16 @@ invariant "^2.2.4" semver "^5.5.0" +"@babel/compat-data@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.5.tgz#f56db0c4bb1bbbf221b4e81345aab4141e7cb0e9" + integrity sha512-DTsS7cxrsH3by8nqQSpFSyjSfSYl57D6Cf4q8dW3LK83tBKBDCkfcay1nYkXq1nIHXnpX8WMMb/O25HOy3h1zg== + +"@babel/compat-data@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== + "@babel/core@7.10.5": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.5.tgz#1f15e2cca8ad9a1d78a38ddba612f5e7cdbbd330" @@ -83,7 +101,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.7.5", "@babel/core@^7.9.0": +"@babel/core@>=7.9.0", "@babel/core@^7.1.0", "@babel/core@^7.7.5", "@babel/core@^7.9.0": version "7.11.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg== @@ -105,6 +123,27 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/generator@^7.10.5", "@babel/generator@^7.11.5", "@babel/generator@^7.11.6", "@babel/generator@^7.4.4", "@babel/generator@^7.9.6": version "7.11.6" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" @@ -114,6 +153,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.12.10", "@babel/generator@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== + dependencies: + "@babel/types" "^7.12.11" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" @@ -121,6 +169,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-annotate-as-pure@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== + dependencies: + "@babel/types" "^7.12.10" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" @@ -157,6 +212,16 @@ levenary "^1.1.1" semver "^5.5.0" +"@babel/helper-compilation-targets@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== + dependencies: + "@babel/compat-data" "^7.12.5" + "@babel/helper-validator-option" "^7.12.1" + browserslist "^4.14.5" + semver "^5.5.0" + "@babel/helper-create-class-features-plugin@^7.10.4", "@babel/helper-create-class-features-plugin@^7.10.5", "@babel/helper-create-class-features-plugin@^7.3.0": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" @@ -169,6 +234,17 @@ "@babel/helper-replace-supers" "^7.10.4" "@babel/helper-split-export-declaration" "^7.10.4" +"@babel/helper-create-class-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" + integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.12.1" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/helper-create-regexp-features-plugin@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" @@ -178,6 +254,15 @@ "@babel/helper-regex" "^7.10.4" regexpu-core "^4.7.0" +"@babel/helper-create-regexp-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.1.tgz#18b1302d4677f9dc4740fe8c9ed96680e29d37e8" + integrity sha512-rsZ4LGvFTZnzdNZR5HZdmJVuXK8834R5QkF3WvcnBhrlVtF0HSIUC6zbreL9MgjTywhKokn8RIYRiq99+DLAxA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + regexpu-core "^4.7.1" + "@babel/helper-define-map@^7.10.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" @@ -204,6 +289,15 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-function-name@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" + "@babel/helper-get-function-arity@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" @@ -211,6 +305,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-get-function-arity@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== + dependencies: + "@babel/types" "^7.12.10" + "@babel/helper-hoist-variables@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" @@ -225,6 +326,13 @@ dependencies: "@babel/types" "^7.11.0" +"@babel/helper-member-expression-to-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" + integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== + dependencies: + "@babel/types" "^7.12.1" + "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" @@ -232,6 +340,13 @@ dependencies: "@babel/types" "^7.10.4" +"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== + dependencies: + "@babel/types" "^7.12.5" + "@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" @@ -245,6 +360,21 @@ "@babel/types" "^7.11.0" lodash "^4.17.19" +"@babel/helper-module-transforms@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + lodash "^4.17.19" + "@babel/helper-optimise-call-expression@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" @@ -275,6 +405,15 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-remap-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" + integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/types" "^7.12.1" + "@babel/helper-replace-supers@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" @@ -285,6 +424,16 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-replace-supers@^7.12.1": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz#f009a17543bbbbce16b06206ae73b63d3fca68d9" + integrity sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.12.1" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" + "@babel/helper-simple-access@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" @@ -293,6 +442,13 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helper-simple-access@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== + dependencies: + "@babel/types" "^7.12.1" + "@babel/helper-skip-transparent-expression-wrappers@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" @@ -300,6 +456,13 @@ dependencies: "@babel/types" "^7.11.0" +"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== + dependencies: + "@babel/types" "^7.12.1" + "@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" @@ -307,11 +470,33 @@ dependencies: "@babel/types" "^7.11.0" +"@babel/helper-split-export-declaration@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== + dependencies: + "@babel/types" "^7.12.11" + "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== +"@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/helper-validator-option@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9" + integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A== + +"@babel/helper-validator-option@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== + "@babel/helper-wrap-function@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" @@ -331,6 +516,15 @@ "@babel/traverse" "^7.10.4" "@babel/types" "^7.10.4" +"@babel/helpers@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" + "@babel/highlight@^7.10.4", "@babel/highlight@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" @@ -340,11 +534,16 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.10.5", "@babel/parser@^7.11.2", "@babel/parser@^7.11.5", "@babel/parser@^7.2.0", "@babel/parser@^7.4.5", "@babel/parser@^7.9.6": +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.10.5", "@babel/parser@^7.11.5", "@babel/parser@^7.2.0", "@babel/parser@^7.4.5", "@babel/parser@^7.9.6": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== +"@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.7.0": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== + "@babel/plugin-proposal-async-generator-functions@^7.10.4", "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" @@ -354,6 +553,15 @@ "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" +"@babel/plugin-proposal-async-generator-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e" + integrity sha512-d+/o30tJxFxrA1lhzJqiUcEJdI6jKlNregCv5bASeGf2Q4MXmnwH7viDo7nhx1/ohf09oaH8j1GVYG/e3Yqk6A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-proposal-class-properties@7.3.0": version "7.3.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.3.0.tgz#272636bc0fa19a0bc46e601ec78136a173ea36cd" @@ -370,6 +578,14 @@ "@babel/helper-create-class-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-proposal-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" + integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-decorators@^7.8.3": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.10.5.tgz#42898bba478bc4b1ae242a703a953a7ad350ffb4" @@ -387,6 +603,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" +"@babel/plugin-proposal-dynamic-import@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" + integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-proposal-export-default-from@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.10.4.tgz#08f66eef0067cbf6a7bc036977dcdccecaf0c6c5" @@ -403,6 +627,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" +"@babel/plugin-proposal-export-namespace-from@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" + integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-proposal-json-strings@^7.10.4", "@babel/plugin-proposal-json-strings@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" @@ -411,6 +643,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" +"@babel/plugin-proposal-json-strings@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" + integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-proposal-logical-assignment-operators@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" @@ -419,6 +659,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" +"@babel/plugin-proposal-logical-assignment-operators@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" + integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-proposal-nullish-coalescing-operator@^7.10.1", "@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" @@ -427,6 +675,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" + integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-proposal-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" @@ -435,6 +691,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-numeric-separator" "^7.10.4" +"@babel/plugin-proposal-numeric-separator@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz#50129ac216b9a6a55b3853fdd923e74bf553a4c0" @@ -461,6 +725,15 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.10.4" +"@babel/plugin-proposal-object-rest-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding@^7.10.4", "@babel/plugin-proposal-optional-catch-binding@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" @@ -469,6 +742,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" +"@babel/plugin-proposal-optional-catch-binding@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" + integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-proposal-optional-chaining@^7.10.1", "@babel/plugin-proposal-optional-chaining@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" @@ -478,6 +759,15 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" +"@babel/plugin-proposal-optional-chaining@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-proposal-private-methods@^7.10.4", "@babel/plugin-proposal-private-methods@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" @@ -486,6 +776,14 @@ "@babel/helper-create-class-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-proposal-private-methods@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" + integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" @@ -494,6 +792,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-proposal-unicode-property-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" + integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-async-generators@^7.2.0", "@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -515,6 +821,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" + integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-decorators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.4.tgz#6853085b2c429f9d322d02f5a635018cdeb2360c" @@ -571,6 +884,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-jsx@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" @@ -613,7 +933,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.10.4", "@babel/plugin-syntax-top-level-await@^7.8.3": +"@babel/plugin-syntax-top-level-await@^7.10.4", "@babel/plugin-syntax-top-level-await@^7.12.1", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== @@ -627,6 +947,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-syntax-typescript@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.1.tgz#460ba9d77077653803c3dd2e673f76d66b4029e5" + integrity sha512-UZNEcCY+4Dp9yYRCAHrHDU+9ZXLYaY9MgBXSRLkB9WjYFRR6quJBumfVrEkUxrePPBwFcpWfNKXqVRQQtm7mMA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-arrow-functions@^7.10.4", "@babel/plugin-transform-arrow-functions@^7.2.0", "@babel/plugin-transform-arrow-functions@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" @@ -634,6 +961,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-arrow-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" + integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-async-to-generator@^7.10.4", "@babel/plugin-transform-async-to-generator@^7.4.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" @@ -643,6 +977,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-remap-async-to-generator" "^7.10.4" +"@babel/plugin-transform-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" + integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" + "@babel/plugin-transform-block-scoped-functions@^7.10.4", "@babel/plugin-transform-block-scoped-functions@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" @@ -650,6 +993,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-block-scoped-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" + integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-block-scoping@^7.10.4", "@babel/plugin-transform-block-scoping@^7.4.4", "@babel/plugin-transform-block-scoping@^7.8.3": version "7.11.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" @@ -657,6 +1007,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-block-scoping@^7.12.11": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-classes@^7.10.4", "@babel/plugin-transform-classes@^7.4.4", "@babel/plugin-transform-classes@^7.9.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" @@ -671,6 +1028,20 @@ "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" + integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.10.4" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.10.4", "@babel/plugin-transform-computed-properties@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" @@ -678,6 +1049,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-computed-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" + integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-destructuring@^7.10.4", "@babel/plugin-transform-destructuring@^7.4.4", "@babel/plugin-transform-destructuring@^7.9.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" @@ -685,6 +1063,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-destructuring@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" + integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" @@ -693,6 +1078,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-dotall-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" + integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-duplicate-keys@^7.10.4", "@babel/plugin-transform-duplicate-keys@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" @@ -700,6 +1093,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-duplicate-keys@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" + integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator@^7.10.4", "@babel/plugin-transform-exponentiation-operator@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" @@ -708,6 +1108,14 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-exponentiation-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" + integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-flow-strip-types@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.10.4.tgz#c497957f09e86e3df7296271e9eb642876bf7788" @@ -723,6 +1131,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-for-of@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" + integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-function-name@^7.10.4", "@babel/plugin-transform-function-name@^7.4.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" @@ -731,6 +1146,14 @@ "@babel/helper-function-name" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-function-name@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" + integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-literals@^7.10.4", "@babel/plugin-transform-literals@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" @@ -738,6 +1161,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" + integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-member-expression-literals@^7.10.4", "@babel/plugin-transform-member-expression-literals@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" @@ -745,6 +1175,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-member-expression-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" + integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-modules-amd@^7.10.4", "@babel/plugin-transform-modules-amd@^7.2.0": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" @@ -754,6 +1191,15 @@ "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-amd@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" + integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@^7.10.4", "@babel/plugin-transform-modules-commonjs@^7.4.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" @@ -764,6 +1210,16 @@ "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-commonjs@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" + integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.12.1" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-systemjs@^7.10.4", "@babel/plugin-transform-modules-systemjs@^7.4.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" @@ -774,6 +1230,17 @@ "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-systemjs@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" + integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== + dependencies: + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-identifier" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-umd@^7.10.4", "@babel/plugin-transform-modules-umd@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" @@ -782,6 +1249,14 @@ "@babel/helper-module-transforms" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-modules-umd@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" + integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex@^7.10.4", "@babel/plugin-transform-named-capturing-groups-regex@^7.4.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" @@ -789,6 +1264,13 @@ dependencies: "@babel/helper-create-regexp-features-plugin" "^7.10.4" +"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" + integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/plugin-transform-new-target@^7.10.4", "@babel/plugin-transform-new-target@^7.4.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" @@ -796,6 +1278,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-new-target@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" + integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-object-super@^7.10.4", "@babel/plugin-transform-object-super@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" @@ -804,6 +1293,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-replace-supers" "^7.10.4" +"@babel/plugin-transform-object-super@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" + integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/plugin-transform-parameters@^7.10.4", "@babel/plugin-transform-parameters@^7.4.4", "@babel/plugin-transform-parameters@^7.9.5": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" @@ -812,6 +1309,13 @@ "@babel/helper-get-function-arity" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-parameters@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" + integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-property-literals@^7.10.4", "@babel/plugin-transform-property-literals@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" @@ -819,6 +1323,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-property-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" + integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-constant-elements@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.10.4.tgz#0f485260bf1c29012bb973e7e404749eaac12c9e" @@ -833,6 +1344,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-react-display-name@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" + integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-jsx-development@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" @@ -842,6 +1360,13 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" +"@babel/plugin-transform-react-jsx-development@^7.12.7": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" + integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.12.12" + "@babel/plugin-transform-react-jsx-self@^7.0.0", "@babel/plugin-transform-react-jsx-self@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" @@ -868,6 +1393,17 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" +"@babel/plugin-transform-react-jsx@^7.12.10", "@babel/plugin-transform-react-jsx@^7.12.12": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e" + integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.12.10" + "@babel/helper-module-imports" "^7.12.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.12.1" + "@babel/types" "^7.12.12" + "@babel/plugin-transform-react-pure-annotations@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501" @@ -876,6 +1412,14 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-react-pure-annotations@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" + integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-regenerator@^7.10.4", "@babel/plugin-transform-regenerator@^7.4.5": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" @@ -883,6 +1427,13 @@ dependencies: regenerator-transform "^0.14.2" +"@babel/plugin-transform-regenerator@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" + integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== + dependencies: + regenerator-transform "^0.14.2" + "@babel/plugin-transform-reserved-words@^7.10.4", "@babel/plugin-transform-reserved-words@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" @@ -890,6 +1441,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-reserved-words@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" + integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-runtime@7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.2.0.tgz#566bc43f7d0aedc880eaddbd29168d0f248966ea" @@ -900,14 +1458,13 @@ resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-runtime@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz#e27f78eb36f19448636e05c33c90fd9ad9b8bccf" - integrity sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw== +"@babel/plugin-transform-runtime@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz#af0fded4e846c4b37078e8e5d06deac6cd848562" + integrity sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA== dependencies: - "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-module-imports" "^7.12.5" "@babel/helper-plugin-utils" "^7.10.4" - resolve "^1.8.1" semver "^5.5.1" "@babel/plugin-transform-shorthand-properties@^7.10.4", "@babel/plugin-transform-shorthand-properties@^7.2.0", "@babel/plugin-transform-shorthand-properties@^7.8.3": @@ -917,6 +1474,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-shorthand-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" + integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-spread@^7.11.0", "@babel/plugin-transform-spread@^7.2.0", "@babel/plugin-transform-spread@^7.8.3": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" @@ -925,6 +1489,14 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" +"@babel/plugin-transform-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" + integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + "@babel/plugin-transform-sticky-regex@^7.10.4", "@babel/plugin-transform-sticky-regex@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" @@ -933,6 +1505,13 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/helper-regex" "^7.10.4" +"@babel/plugin-transform-sticky-regex@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-template-literals@^7.10.4", "@babel/plugin-transform-template-literals@^7.4.4", "@babel/plugin-transform-template-literals@^7.8.3": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" @@ -941,6 +1520,13 @@ "@babel/helper-annotate-as-pure" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-template-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" + integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-typeof-symbol@^7.10.4", "@babel/plugin-transform-typeof-symbol@^7.2.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" @@ -948,6 +1534,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-typeof-symbol@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-typescript@^7.10.4": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz#2b4879676af37342ebb278216dd090ac67f13abb" @@ -957,6 +1550,15 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-typescript" "^7.10.4" +"@babel/plugin-transform-typescript@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.12.1.tgz#d92cc0af504d510e26a754a7dbc2e5c8cd9c7ab4" + integrity sha512-VrsBByqAIntM+EYMqSm59SiMEf7qkmI9dqMt6RbD/wlwueWmYcI0FFK5Fj47pP6DRZm+3teXjosKlwcZJ5lIMw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-typescript" "^7.12.1" + "@babel/plugin-transform-unicode-escapes@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" @@ -964,6 +1566,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-unicode-escapes@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" + integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-unicode-regex@^7.10.4", "@babel/plugin-transform-unicode-regex@^7.4.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" @@ -972,6 +1581,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.10.4" "@babel/helper-plugin-utils" "^7.10.4" +"@babel/plugin-transform-unicode-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" + integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/preset-env@7.4.5": version "7.4.5" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.5.tgz#2fad7f62983d5af563b5f3139242755884998a58" @@ -1026,7 +1643,79 @@ js-levenshtein "^1.1.3" semver "^5.5.0" -"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.9.5", "@babel/preset-env@^7.9.6": +"@babel/preset-env@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== + dependencies: + "@babel/compat-data" "^7.12.7" + "@babel/helper-compilation-targets" "^7.12.5" + "@babel/helper-module-imports" "^7.12.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-option" "^7.12.11" + "@babel/plugin-proposal-async-generator-functions" "^7.12.1" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-dynamic-import" "^7.12.1" + "@babel/plugin-proposal-export-namespace-from" "^7.12.1" + "@babel/plugin-proposal-json-strings" "^7.12.1" + "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-numeric-separator" "^7.12.7" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.12.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.12.1" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-async-to-generator" "^7.12.1" + "@babel/plugin-transform-block-scoped-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.11" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-computed-properties" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-dotall-regex" "^7.12.1" + "@babel/plugin-transform-duplicate-keys" "^7.12.1" + "@babel/plugin-transform-exponentiation-operator" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-function-name" "^7.12.1" + "@babel/plugin-transform-literals" "^7.12.1" + "@babel/plugin-transform-member-expression-literals" "^7.12.1" + "@babel/plugin-transform-modules-amd" "^7.12.1" + "@babel/plugin-transform-modules-commonjs" "^7.12.1" + "@babel/plugin-transform-modules-systemjs" "^7.12.1" + "@babel/plugin-transform-modules-umd" "^7.12.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" + "@babel/plugin-transform-new-target" "^7.12.1" + "@babel/plugin-transform-object-super" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-property-literals" "^7.12.1" + "@babel/plugin-transform-regenerator" "^7.12.1" + "@babel/plugin-transform-reserved-words" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/plugin-transform-sticky-regex" "^7.12.7" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/plugin-transform-typeof-symbol" "^7.12.10" + "@babel/plugin-transform-unicode-escapes" "^7.12.1" + "@babel/plugin-transform-unicode-regex" "^7.12.1" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.12.11" + core-js-compat "^3.8.0" + semver "^5.5.0" + +"@babel/preset-env@^7.9.5", "@babel/preset-env@^7.9.6": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== @@ -1130,7 +1819,7 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" -"@babel/preset-react@^7.0.0", "@babel/preset-react@^7.10.4", "@babel/preset-react@^7.8.3", "@babel/preset-react@^7.9.4": +"@babel/preset-react@^7.0.0", "@babel/preset-react@^7.8.3", "@babel/preset-react@^7.9.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== @@ -1143,7 +1832,27 @@ "@babel/plugin-transform-react-jsx-source" "^7.10.4" "@babel/plugin-transform-react-pure-annotations" "^7.10.4" -"@babel/preset-typescript@^7.10.4", "@babel/preset-typescript@^7.9.0": +"@babel/preset-react@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" + integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.12.1" + "@babel/plugin-transform-react-jsx" "^7.12.10" + "@babel/plugin-transform-react-jsx-development" "^7.12.7" + "@babel/plugin-transform-react-pure-annotations" "^7.12.1" + +"@babel/preset-typescript@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.12.7.tgz#fc7df8199d6aae747896f1e6c61fc872056632a3" + integrity sha512-nOoIqIqBmHBSEgBXWR4Dv/XBehtIFcw9PqZw6rFYuKrzsZmOQm3PR5siLBnKZFEsDb03IegG8nSjU/iXXXYRmw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-option" "^7.12.1" + "@babel/plugin-transform-typescript" "^7.12.1" + +"@babel/preset-typescript@^7.9.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.10.4.tgz#7d5d052e52a682480d6e2cc5aa31be61c8c25e36" integrity sha512-SdYnvGPv+bLlwkF2VkJnaX/ni1sMNetcGI1+nThF1gyv6Ph8Qucc4ZZAjM5yZcE/AKRXIOTZz7eSRDWOEjPyRQ== @@ -1162,6 +1871,17 @@ pirates "^4.0.0" source-map-support "^0.5.16" +"@babel/register@^7.12.10": + version "7.12.10" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.12.10.tgz#19b87143f17128af4dbe7af54c735663b3999f60" + integrity sha512-EvX/BvMMJRAA3jZgILWgbsrHwBQvllC5T8B29McyME8DvkdOxk4ujESfrMvME8IHSDvWXrmMXxPvA/lx2gqPLQ== + dependencies: + find-cache-dir "^2.0.0" + lodash "^4.17.19" + make-dir "^2.1.0" + pirates "^4.0.0" + source-map-support "^0.5.16" + "@babel/runtime-corejs2@^7.2.0": version "7.11.2" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.11.2.tgz#700a03945ebad0d31ba6690fc8a6bcc9040faa47" @@ -1199,6 +1919,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4", "@babel/template@^7.3.3", "@babel/template@^7.4.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -1208,7 +1935,16 @@ "@babel/parser" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.6", "@babel/traverse@^7.10.4", "@babel/traverse@^7.10.5", "@babel/traverse@^7.11.5", "@babel/traverse@^7.4.5": +"@babel/template@^7.12.7": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.1.6", "@babel/traverse@^7.10.4", "@babel/traverse@^7.10.5", "@babel/traverse@^7.11.5", "@babel/traverse@^7.4.5": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ== @@ -1223,6 +1959,21 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.12", "@babel/traverse@^7.12.5", "@babel/traverse@^7.7.0": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== + dependencies: + "@babel/code-frame" "^7.12.11" + "@babel/generator" "^7.12.11" + "@babel/helper-function-name" "^7.12.11" + "@babel/helper-split-export-declaration" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/types" "^7.12.12" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.9.5": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" @@ -1232,6 +1983,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.7.0": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@base2/pretty-print-object@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.0.tgz#860ce718b0b73f4009e153541faff2cb6b85d047" @@ -3061,6 +3821,23 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents": + version "2.1.8-no-fsevents" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.tgz#da7c3996b8e6e19ebd14d82eaced2313e7769f9b" + integrity sha512-+nb9vWloHNNMFHjGofEam3wopE3m1yuambrrd/fnPc+lFOMB9ROTqQlche9ByFWNkdNqfSgR/kkQtQ8DzEWt2w== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + "@nodelib/fs.scandir@2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" @@ -4555,7 +5332,7 @@ resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.4.tgz#bfd5b0d0d1ba13e351dff65b6e52783b816826c8" integrity sha512-WiZhq3SVJHFRgRYLXvpf65XnV6ipVHhnNaNvE8yCimejrGglkg38kEj0JcizqwSHxmPSjcTlig/6JouxLGEhGw== -"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.10", "@types/babel__core@^7.1.7": +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.10" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.10.tgz#ca58fc195dd9734e77e57c6f2df565623636ab40" integrity sha512-x8OM8XzITIMyiwl5Vmo2B1cR1S1Ipkyv4mdlbJjMa1lmuKvKY9FrBbEANIaMlnWn5Rf7uO+rC/VgYabNkE17Hw== @@ -4566,6 +5343,17 @@ "@types/babel__template" "*" "@types/babel__traverse" "*" +"@types/babel__core@^7.1.12": + version "7.1.12" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d" + integrity sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + "@types/babel__generator@*": version "7.0.2" resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.0.2.tgz#d2112a6b21fad600d7674274293c85dce0cb47fc" @@ -7492,6 +8280,11 @@ async-done@^1.2.0, async-done@^1.2.2: process-nextick-args "^2.0.0" stream-exhaust "^1.0.1" +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" @@ -7675,15 +8468,15 @@ babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-eslint@^10.0.3: - version "10.0.3" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" - integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" eslint-visitor-keys "^1.0.0" resolve "^1.12.0" @@ -7736,7 +8529,7 @@ babel-helper-to-multiple-sequence-expressions@^0.5.0: resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz#a3f924e3561882d42fcf48907aa98f7979a4588d" integrity sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA== -babel-jest@^26.3.0, babel-jest@^26.6.3: +babel-jest@^26.6.3: version "26.6.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== @@ -7760,6 +8553,16 @@ babel-loader@^8.0.6: mkdirp "^0.5.1" pify "^4.0.1" +babel-loader@^8.2.2: + version "8.2.2" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" + integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^1.4.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + babel-messages@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" @@ -7767,13 +8570,18 @@ babel-messages@^6.23.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-add-module-exports@1.0.2, babel-plugin-add-module-exports@^1.0.2: +babel-plugin-add-module-exports@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.2.tgz#96cd610d089af664f016467fc4567c099cce2d9c" integrity sha512-4paN7RivvU3Rzju1vGSHWPjO8Y0rI6droWvSFKI6dvEQ4mvoV0zGojnlzVRfI6N8zISo6VERXt3coIuVmzuvNg== optionalDependencies: chokidar "^2.0.4" +babel-plugin-add-module-exports@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.4.tgz#6caa4ddbe1f578c6a5264d4d3e6c8a2720a7ca2b" + integrity sha512-g+8yxHUZ60RcyaUpfNzy56OtWW+x9cyEe9j+CranqLiqbju2yf/Cy6ZtYK40EZxtrdHllzlVZgLmcOUCTlJ7Jg== + babel-plugin-add-react-displayname@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/babel-plugin-add-react-displayname/-/babel-plugin-add-react-displayname-0.0.5.tgz#339d4cddb7b65fd62d1df9db9fe04de134122bd5" @@ -8304,6 +9112,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + binary-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" @@ -8450,7 +9263,7 @@ brace@0.11.1, brace@^0.11.0, brace@^0.11.1: resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.1.tgz#4896fcc9d544eef45f4bb7660db320d3b379fe58" integrity sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg= -braces@^2.3.1: +braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -8746,6 +9559,28 @@ browserslist@^4.12.0, browserslist@^4.8.3: node-releases "^1.1.53" pkg-up "^2.0.0" +browserslist@^4.14.5: + version "4.14.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.7.tgz#c071c1b3622c1c2e790799a37bb09473a4351cb6" + integrity sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ== + dependencies: + caniuse-lite "^1.0.30001157" + colorette "^1.2.1" + electron-to-chromium "^1.3.591" + escalade "^3.1.1" + node-releases "^1.1.66" + +browserslist@^4.16.1: + version "4.16.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766" + integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA== + dependencies: + caniuse-lite "^1.0.30001173" + colorette "^1.2.1" + electron-to-chromium "^1.3.634" + escalade "^3.1.1" + node-releases "^1.1.69" + browserslist@^4.6.0, browserslist@^4.8.5: version "4.14.5" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.5.tgz#1c751461a102ddc60e40993639b709be7f2c4015" @@ -9100,11 +9935,16 @@ camelize@^1.0.0: resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= -caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001097, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001135: +caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001097, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001135, caniuse-lite@^1.0.30001173: version "1.0.30001179" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001179.tgz" integrity sha512-blMmO0QQujuUWZKyVrD1msR4WNDAqb/UPO1Sw2WWsQ7deoM5bJiicKnWJ1Y0NS/aGINSnKPIWBMw5luX+NDUCA== +caniuse-lite@^1.0.30001157: + version "1.0.30001164" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001164.tgz#5bbfd64ca605d43132f13cc7fdabb17c3036bfdc" + integrity sha512-G+A/tkf4bu0dSp9+duNiXc7bGds35DioCyC6vgK2m/rjA4Krpy5WeZgZyfH2f0wj2kI6yAWWucyap6oOwmY1mg== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -9343,7 +10183,7 @@ cheerio@^1.0.0-rc.3: lodash "^4.15.0" parse5 "^3.0.1" -chokidar@2.1.2, chokidar@3.3.0, chokidar@^2.0.0, chokidar@^2.0.4, chokidar@^2.1.1, chokidar@^2.1.2, chokidar@^2.1.8, chokidar@^3.2.2, chokidar@^3.3.0, chokidar@^3.4.1, chokidar@^3.4.3: +chokidar@2.1.2, chokidar@3.3.0, chokidar@^2.0.0, chokidar@^2.0.4, chokidar@^2.1.1, chokidar@^2.1.2, chokidar@^2.1.8, chokidar@^3.2.2, chokidar@^3.3.0, chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== @@ -10226,6 +11066,14 @@ core-js-compat@^3.6.2: browserslist "^4.8.3" semver "7.0.0" +core-js-compat@^3.8.0: + version "3.8.3" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" + integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== + dependencies: + browserslist "^4.16.1" + semver "7.0.0" + core-js-pure@^3.0.0, core-js-pure@^3.0.1: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" @@ -12191,6 +13039,16 @@ electron-to-chromium@^1.3.571: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.577.tgz#9885f3f72c6e3367010b461ff6f2d9624a929720" integrity sha512-dSb64JQSFif/pD8mpVAgSFkbVi6YHbK6JeEziwNNmXlr/Ne2rZtseFK5SM7JoWSLf6gP0gVvRGi4/2ZRhSX/rA== +electron-to-chromium@^1.3.591: + version "1.3.598" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.598.tgz#8f757018902ab6190323a8c5f6124d854893a35b" + integrity sha512-G5Ztk23/ubLYVPxPXnB1uu105uzIPd4xB/D8ld8x1GaSC9+vU9NZL16nYZya8H77/7CCKKN7dArzJL3pBs8N7A== + +electron-to-chromium@^1.3.634: + version "1.3.642" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.642.tgz#8b884f50296c2ae2a9997f024d0e3e57facc2b94" + integrity sha512-cev+jOrz/Zm1i+Yh334Hed6lQVOkkemk2wRozfMF4MtTR7pxf3r3L5Rbd7uX1zMcEqVJ7alJBnJL7+JffkC6FQ== + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" @@ -12740,10 +13598,10 @@ eslint-module-utils@2.5.0, eslint-module-utils@^2.4.1: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-babel@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.0.tgz#2e7f251ccc249326da760c1a4c948a91c32d0023" - integrity sha512-HPuNzSPE75O+SnxHIafbW5QB45r2w78fxqwK3HmjqIUoPfPzVrq6rD+CINU3yzoDSzEhUkX07VUphbF73Lth/w== +eslint-plugin-babel@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-babel/-/eslint-plugin-babel-5.3.1.tgz#75a2413ffbf17e7be57458301c60291f2cfbf560" + integrity sha512-VsQEr6NH3dj664+EyxJwO4FCYm/00JhYb3Sk3ft8o+fpKuIfQ9TaW6uVUfvwMXHcf/lsnRIoyFPsLMyiWCSL/g== dependencies: eslint-rule-composer "^0.3.0" @@ -16486,6 +17344,13 @@ is-bigint@^1.0.0: resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4" integrity sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g== +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -20656,6 +21521,16 @@ node-releases@^1.1.61: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e" integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g== +node-releases@^1.1.66: + version "1.1.67" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12" + integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg== + +node-releases@^1.1.69: + version "1.1.70" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" + integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw== + node-sass@^4.14.1: version "4.14.1" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" @@ -23847,6 +24722,15 @@ readdir-scoped-modules@^1.0.0: graceful-fs "^4.1.2" once "^1.3.0" +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + readdirp@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" @@ -24102,6 +24986,18 @@ regexpu-core@^4.7.0: unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.2.0" +regexpu-core@^4.7.1: + version "4.7.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + registry-auth-token@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" @@ -28175,6 +29071,11 @@ unzip-response@^1.0.0: resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" integrity sha1-uYTwh3/AqJwsdzzB73tbIytbBv4= +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + update-notifier@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc" From 0076384a0f9de9d35711008eaa8b244a2d6a487c Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 26 Jan 2021 12:32:12 -0500 Subject: [PATCH 19/21] [Maps] Implement fields and bounds retrieval on GeoJsonFileSource (#88294) --- .../source_descriptor_types.ts | 6 + .../classes/fields/geojson_file_field.ts | 43 +++++++ .../layers/file_upload_wizard/wizard.tsx | 7 +- .../geojson_file_source/geojson_file.test.ts | 105 ++++++++++++++++++ .../geojson_file_source.ts | 88 ++++++++++++--- .../sources/geojson_file_source/index.ts | 2 +- .../maps/public/selectors/map_selectors.ts | 12 +- 7 files changed, 240 insertions(+), 23 deletions(-) create mode 100644 x-pack/plugins/maps/public/classes/fields/geojson_file_field.ts create mode 100644 x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file.test.ts diff --git a/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts index 603e1d767e1c6..b849b42429cf6 100644 --- a/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/source_descriptor_types.ts @@ -156,7 +156,13 @@ export type TiledSingleLayerVectorSourceDescriptor = AbstractSourceDescriptor & tooltipProperties: string[]; }; +export type GeoJsonFileFieldDescriptor = { + name: string; + type: 'string' | 'number'; +}; + export type GeojsonFileSourceDescriptor = { + __fields?: GeoJsonFileFieldDescriptor[]; __featureCollection: FeatureCollection; name: string; type: string; diff --git a/x-pack/plugins/maps/public/classes/fields/geojson_file_field.ts b/x-pack/plugins/maps/public/classes/fields/geojson_file_field.ts new file mode 100644 index 0000000000000..ae42b09d491c5 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/fields/geojson_file_field.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FIELD_ORIGIN } from '../../../common/constants'; +import { IField, AbstractField } from './field'; +import { IVectorSource } from '../sources/vector_source'; +import { GeoJsonFileSource } from '../sources/geojson_file_source'; + +export class GeoJsonFileField extends AbstractField implements IField { + private readonly _source: GeoJsonFileSource; + private readonly _dataType: string; + + constructor({ + fieldName, + source, + origin, + dataType, + }: { + fieldName: string; + source: GeoJsonFileSource; + origin: FIELD_ORIGIN; + dataType: string; + }) { + super({ fieldName, origin }); + this._source = source; + this._dataType = dataType; + } + + getSource(): IVectorSource { + return this._source; + } + + async getLabel(): Promise { + return this.getName(); + } + + async getDataType(): Promise { + return this._dataType; + } +} diff --git a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx b/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx index a0029c5c64e0b..68fd25ce9e7ae 100644 --- a/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/file_upload_wizard/wizard.tsx @@ -14,7 +14,7 @@ import { SCALING_TYPES, } from '../../../../common/constants'; import { getFileUploadComponent } from '../../../kibana_services'; -import { GeojsonFileSource } from '../../sources/geojson_file_source'; +import { GeoJsonFileSource } from '../../sources/geojson_file_source'; import { VectorLayer } from '../../layers/vector_layer/vector_layer'; import { createDefaultLayerDescriptor } from '../../sources/es_search_source'; import { RenderWizardArguments } from '../../layers/layer_wizard_registry'; @@ -79,7 +79,10 @@ export class ClientFileCreateSourceEditor extends Component { + describe('getName', () => { + it('should get default display name', async () => { + const geojsonFileSource = new GeoJsonFileSource({}); + expect(await geojsonFileSource.getDisplayName()).toBe('Features'); + }); + }); + describe('getBounds', () => { + it('should get null bounds', async () => { + const geojsonFileSource = new GeoJsonFileSource({}); + expect( + await geojsonFileSource.getBoundsForFilters(({} as unknown) as BoundsFilters, () => {}) + ).toEqual(null); + }); + + it('should get bounds from feature collection', async () => { + const geojsonFileSource = new GeoJsonFileSource({ + __featureCollection: { + type: 'FeatureCollection', + features: [ + { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [0, 1], + }, + properties: {}, + }, + { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [2, 3], + }, + properties: {}, + }, + ], + }, + }); + + expect(geojsonFileSource.isBoundsAware()).toBe(true); + expect( + await geojsonFileSource.getBoundsForFilters(({} as unknown) as BoundsFilters, () => {}) + ).toEqual({ + maxLat: 3, + maxLon: 2, + minLat: 1, + minLon: 0, + }); + }); + }); + + describe('getFields', () => { + it('should get fields from config', async () => { + const geojsonFileSource = new GeoJsonFileSource({ + __fields: [ + { + type: 'string', + name: 'foo', + }, + { + type: 'number', + name: 'bar', + }, + ], + }); + + const fields = await geojsonFileSource.getFields(); + + const actualFields = fields.map(async (field) => { + return { + dataType: await field.getDataType(), + origin: field.getOrigin(), + name: field.getName(), + source: field.getSource(), + }; + }); + + expect(await Promise.all(actualFields)).toEqual([ + { + dataType: 'string', + origin: FIELD_ORIGIN.SOURCE, + source: geojsonFileSource, + name: 'foo', + }, + { + dataType: 'number', + origin: FIELD_ORIGIN.SOURCE, + source: geojsonFileSource, + name: 'bar', + }, + ]); + }); + }); +}); diff --git a/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file_source.ts b/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file_source.ts index 6172405152739..69d84dc65d382 100644 --- a/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/geojson_file_source/geojson_file_source.ts @@ -5,13 +5,22 @@ */ import { Feature, FeatureCollection } from 'geojson'; -import { AbstractVectorSource, GeoJsonWithMeta } from '../vector_source'; -import { EMPTY_FEATURE_COLLECTION, SOURCE_TYPES } from '../../../../common/constants'; -import { GeojsonFileSourceDescriptor } from '../../../../common/descriptor_types'; +import { AbstractVectorSource, BoundsFilters, GeoJsonWithMeta } from '../vector_source'; +import { EMPTY_FEATURE_COLLECTION, FIELD_ORIGIN, SOURCE_TYPES } from '../../../../common/constants'; +import { + GeoJsonFileFieldDescriptor, + GeojsonFileSourceDescriptor, + MapExtent, +} from '../../../../common/descriptor_types'; import { registerSource } from '../source_registry'; import { IField } from '../../fields/field'; +import { getFeatureCollectionBounds } from '../../util/get_feature_collection_bounds'; +import { GeoJsonFileField } from '../../fields/geojson_file_field'; +import { Adapters } from '../../../../../../../src/plugins/inspector/common/adapters'; -function getFeatureCollection(geoJson: Feature | FeatureCollection | null): FeatureCollection { +function getFeatureCollection( + geoJson: Feature | FeatureCollection | null | undefined +): FeatureCollection { if (!geoJson) { return EMPTY_FEATURE_COLLECTION; } @@ -30,18 +39,73 @@ function getFeatureCollection(geoJson: Feature | FeatureCollection | null): Feat return EMPTY_FEATURE_COLLECTION; } -export class GeojsonFileSource extends AbstractVectorSource { +export class GeoJsonFileSource extends AbstractVectorSource { static createDescriptor( - geoJson: Feature | FeatureCollection | null, - name: string + descriptor: Partial ): GeojsonFileSourceDescriptor { return { type: SOURCE_TYPES.GEOJSON_FILE, - __featureCollection: getFeatureCollection(geoJson), - name, + __featureCollection: getFeatureCollection(descriptor.__featureCollection), + __fields: descriptor.__fields || [], + name: descriptor.name || 'Features', }; } + constructor(descriptor: Partial, inspectorAdapters?: Adapters) { + const normalizedDescriptor = GeoJsonFileSource.createDescriptor(descriptor); + super(normalizedDescriptor, inspectorAdapters); + } + + _getFields(): GeoJsonFileFieldDescriptor[] { + const fields = (this._descriptor as GeojsonFileSourceDescriptor).__fields; + return fields ? fields : []; + } + + createField({ fieldName }: { fieldName: string }): IField { + const fields = this._getFields(); + const descriptor: GeoJsonFileFieldDescriptor | undefined = fields.find((field) => { + return field.name === fieldName; + }); + + if (!descriptor) { + throw new Error( + `Cannot find corresponding field ${fieldName} in __fields array ${JSON.stringify( + this._getFields() + )} ` + ); + } + return new GeoJsonFileField({ + fieldName: descriptor.name, + source: this, + origin: FIELD_ORIGIN.SOURCE, + dataType: descriptor.type, + }); + } + + async getFields(): Promise { + const fields = this._getFields(); + return fields.map((field: GeoJsonFileFieldDescriptor) => { + return new GeoJsonFileField({ + fieldName: field.name, + source: this, + origin: FIELD_ORIGIN.SOURCE, + dataType: field.type, + }); + }); + } + + isBoundsAware(): boolean { + return true; + } + + async getBoundsForFilters( + boundsFilters: BoundsFilters, + registerCancelCallback: (callback: () => void) => void + ): Promise { + const featureCollection = (this._descriptor as GeojsonFileSourceDescriptor).__featureCollection; + return getFeatureCollectionBounds(featureCollection, false); + } + async getGeoJsonWithMeta(): Promise { return { data: (this._descriptor as GeojsonFileSourceDescriptor).__featureCollection, @@ -49,10 +113,6 @@ export class GeojsonFileSource extends AbstractVectorSource { }; } - createField({ fieldName }: { fieldName: string }): IField { - throw new Error('Not implemented'); - } - async getDisplayName() { return (this._descriptor as GeojsonFileSourceDescriptor).name; } @@ -63,6 +123,6 @@ export class GeojsonFileSource extends AbstractVectorSource { } registerSource({ - ConstructorFunction: GeojsonFileSource, + ConstructorFunction: GeoJsonFileSource, type: SOURCE_TYPES.GEOJSON_FILE, }); diff --git a/x-pack/plugins/maps/public/classes/sources/geojson_file_source/index.ts b/x-pack/plugins/maps/public/classes/sources/geojson_file_source/index.ts index cf0d15dcb747a..ef6806e0aa151 100644 --- a/x-pack/plugins/maps/public/classes/sources/geojson_file_source/index.ts +++ b/x-pack/plugins/maps/public/classes/sources/geojson_file_source/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { GeojsonFileSource } from './geojson_file_source'; +export { GeoJsonFileSource } from './geojson_file_source'; diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index 7b72a3c979abe..8876b9536ce92 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -22,7 +22,7 @@ import { TiledVectorLayer } from '../classes/layers/tiled_vector_layer/tiled_vec import { copyPersistentState, TRACKED_LAYER_DESCRIPTOR } from '../reducers/util'; import { InnerJoin } from '../classes/joins/inner_join'; import { getSourceByType } from '../classes/sources/source_registry'; -import { GeojsonFileSource } from '../classes/sources/geojson_file_source'; +import { GeoJsonFileSource } from '../classes/sources/geojson_file_source'; import { SOURCE_DATA_REQUEST_ID, STYLE_TYPE, @@ -241,10 +241,10 @@ export const getSpatialFiltersLayer = createSelector( type: 'FeatureCollection', features: extractFeaturesFromFilters(filters), }; - const geoJsonSourceDescriptor = GeojsonFileSource.createDescriptor( - featureCollection, - 'spatialFilters' - ); + const geoJsonSourceDescriptor = GeoJsonFileSource.createDescriptor({ + __featureCollection: featureCollection, + name: 'spatialFilters', + }); return new VectorLayer({ layerDescriptor: VectorLayer.createDescriptor({ @@ -272,7 +272,7 @@ export const getSpatialFiltersLayer = createSelector( }, }), }), - source: new GeojsonFileSource(geoJsonSourceDescriptor), + source: new GeoJsonFileSource(geoJsonSourceDescriptor), }); } ); From 3938fa67ad5b404da32b165f0cd8a40ec23765bf Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 26 Jan 2021 10:35:57 -0700 Subject: [PATCH 20/21] [Maps] allow saving maps to dashboards (#88759) * [Maps] allow saving maps to dashboards * update saveMap functional test method * update tags functional test * review feedback Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/maps/kibana.json | 2 +- .../routes/map_page/saved_map/saved_map.ts | 15 ++- .../public/routes/map_page/top_nav_config.tsx | 108 ++++++++++-------- .../apps/maps/embeddable/save_and_return.js | 5 +- .../test/functional/page_objects/gis_page.ts | 18 ++- .../functional/tests/maps_integration.ts | 10 +- 6 files changed, 93 insertions(+), 65 deletions(-) diff --git a/x-pack/plugins/maps/kibana.json b/x-pack/plugins/maps/kibana.json index e47968b027cc3..42adf6f2a950b 100644 --- a/x-pack/plugins/maps/kibana.json +++ b/x-pack/plugins/maps/kibana.json @@ -23,5 +23,5 @@ "ui": true, "server": true, "extraPublicDirs": ["common/constants"], - "requiredBundles": ["kibanaReact", "kibanaUtils", "home", "mapsOss"] + "requiredBundles": ["kibanaReact", "kibanaUtils", "home", "mapsOss", "presentationUtil"] } diff --git a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts index 27fd78980710f..df424124be3f2 100644 --- a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts +++ b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts @@ -281,10 +281,12 @@ export class SavedMap { returnToOrigin, newTags, saveByReference, + dashboardId, }: OnSaveProps & { - returnToOrigin: boolean; + returnToOrigin?: boolean; newTags?: string[]; saveByReference: boolean; + dashboardId?: string | null; }) { if (!this._attributes) { throw new Error('Invalid usage, must await whenReady before calling save'); @@ -337,7 +339,7 @@ export class SavedMap { }); return; } - this._getStateTransfer().navigateToWithEmbeddablePackage(this._originatingApp, { + await this._getStateTransfer().navigateToWithEmbeddablePackage(this._originatingApp, { state: { embeddableId: newCopyOnSave ? undefined : this._embeddableId, type: MAP_SAVED_OBJECT_TYPE, @@ -345,6 +347,15 @@ export class SavedMap { }, }); return; + } else if (dashboardId) { + await this._getStateTransfer().navigateToWithEmbeddablePackage('dashboards', { + state: { + type: MAP_SAVED_OBJECT_TYPE, + input: updatedMapEmbeddableInput, + }, + path: dashboardId === 'new' ? '#/create' : `#/view/${dashboardId}`, + }); + return; } this._mapEmbeddableInput = updatedMapEmbeddableInput; diff --git a/x-pack/plugins/maps/public/routes/map_page/top_nav_config.tsx b/x-pack/plugins/maps/public/routes/map_page/top_nav_config.tsx index 43a74a9c73012..7010c281d24c6 100644 --- a/x-pack/plugins/maps/public/routes/map_page/top_nav_config.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/top_nav_config.tsx @@ -10,6 +10,7 @@ import { Adapters } from 'src/plugins/inspector/public'; import { getCoreChrome, getMapsCapabilities, + getIsAllowByValueEmbeddables, getInspector, getCoreI18n, getSavedObjectsClient, @@ -25,6 +26,7 @@ import { import { MAP_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { SavedMap } from './saved_map'; import { getMapEmbeddableDisplayName } from '../../../common/i18n_getters'; +import { SavedObjectSaveModalDashboard } from '../../../../../../src/plugins/presentation_util/public'; export function getTopNavConfig({ savedMap, @@ -139,53 +141,67 @@ export function getTopNavConfig({ /> ) : undefined; - const saveModal = ( - { - try { - await checkForDuplicateTitle( - { - id: props.newCopyOnSave ? undefined : savedMap.getSavedObjectId(), - title: props.newTitle, - copyOnSave: props.newCopyOnSave, - lastSavedTitle: savedMap.getSavedObjectId() ? savedMap.getTitle() : '', - getEsType: () => MAP_SAVED_OBJECT_TYPE, - getDisplayName: getMapEmbeddableDisplayName, - }, - props.isTitleDuplicateConfirmed, - props.onTitleDuplicate, - { - savedObjectsClient: getSavedObjectsClient(), - overlays: getCoreOverlays(), - } - ); - } catch (e) { - // ignore duplicate title failure, user notified in save modal - return {}; - } + const saveModalProps = { + onSave: async ( + props: OnSaveProps & { returnToOrigin?: boolean; dashboardId?: string | null } + ) => { + try { + await checkForDuplicateTitle( + { + id: props.newCopyOnSave ? undefined : savedMap.getSavedObjectId(), + title: props.newTitle, + copyOnSave: props.newCopyOnSave, + lastSavedTitle: savedMap.getSavedObjectId() ? savedMap.getTitle() : '', + getEsType: () => MAP_SAVED_OBJECT_TYPE, + getDisplayName: getMapEmbeddableDisplayName, + }, + props.isTitleDuplicateConfirmed, + props.onTitleDuplicate, + { + savedObjectsClient: getSavedObjectsClient(), + overlays: getCoreOverlays(), + } + ); + } catch (e) { + // ignore duplicate title failure, user notified in save modal + return {}; + } + + await savedMap.save({ + ...props, + newTags: selectedTags, + saveByReference: !props.dashboardId, + }); + // showSaveModal wrapper requires onSave to return an object with an id to close the modal after successful save + return { id: 'id' }; + }, + onClose: () => {}, + documentInfo: { + description: mapDescription, + id: savedMap.getSavedObjectId(), + title: savedMap.getTitle(), + }, + objectType: i18n.translate('xpack.maps.topNav.saveModalType', { + defaultMessage: 'map', + }), + }; + + const saveModal = + savedMap.getOriginatingApp() || !getIsAllowByValueEmbeddables() ? ( + + ) : ( + + ); - await savedMap.save({ - ...props, - newTags: selectedTags, - saveByReference: true, - }); - // showSaveModal wrapper requires onSave to return an object with an id to close the modal after successful save - return { id: 'id' }; - }} - onClose={() => {}} - documentInfo={{ - description: mapDescription, - id: savedMap.getSavedObjectId(), - title: savedMap.getTitle(), - }} - objectType={i18n.translate('xpack.maps.topNav.saveModalType', { - defaultMessage: 'map', - })} - options={tagSelector} - /> - ); showSaveModal(saveModal, getCoreI18n().Context); }, }); diff --git a/x-pack/test/functional/apps/maps/embeddable/save_and_return.js b/x-pack/test/functional/apps/maps/embeddable/save_and_return.js index 40af8ddb9d44b..13aa08cbbeb38 100644 --- a/x-pack/test/functional/apps/maps/embeddable/save_and_return.js +++ b/x-pack/test/functional/apps/maps/embeddable/save_and_return.js @@ -31,6 +31,7 @@ export default function ({ getPageObjects, getService }) { after(async () => { await security.testUser.restoreDefaults(); }); + describe('new map', () => { beforeEach(async () => { await PageObjects.common.navigateToApp('dashboard'); @@ -55,7 +56,7 @@ export default function ({ getPageObjects, getService }) { it('should cut the originator and stay in maps application', async () => { await PageObjects.maps.saveMap( 'map created from dashboard save and return with originator app cut', - true + false ); await PageObjects.maps.waitForLayersToLoad(); await testSubjects.missingOrFail('mapSaveAndReturnButton'); @@ -94,7 +95,7 @@ export default function ({ getPageObjects, getService }) { describe('save as and uncheck return to origin switch', () => { it('should cut the originator and stay in maps application', async () => { - await PageObjects.maps.saveMap('Clone 2 of map embeddable example', true); + await PageObjects.maps.saveMap('Clone 2 of map embeddable example', false); await PageObjects.maps.waitForLayersToLoad(); await testSubjects.missingOrFail('mapSaveAndReturnButton'); await testSubjects.existOrFail('mapSaveButton'); diff --git a/x-pack/test/functional/page_objects/gis_page.ts b/x-pack/test/functional/page_objects/gis_page.ts index 7e22acf785d36..7767499cb6bd3 100644 --- a/x-pack/test/functional/page_objects/gis_page.ts +++ b/x-pack/test/functional/page_objects/gis_page.ts @@ -9,7 +9,7 @@ import { APP_ID } from '../../../plugins/maps/common/constants'; import { FtrProviderContext } from '../ftr_provider_context'; export function GisPageProvider({ getService, getPageObjects }: FtrProviderContext) { - const PageObjects = getPageObjects(['common', 'header', 'timePicker']); + const PageObjects = getPageObjects(['common', 'header', 'timePicker', 'visualize']); const log = getService('log'); const testSubjects = getService('testSubjects'); @@ -148,18 +148,14 @@ export function GisPageProvider({ getService, getPageObjects }: FtrProviderConte await renderable.waitForRender(); } - async saveMap(name: string, uncheckReturnToOriginModeSwitch = false, tags?: string[]) { + async saveMap(name: string, redirectToOrigin = true, tags?: string[]) { await testSubjects.click('mapSaveButton'); await testSubjects.setValue('savedObjectTitle', name); - if (uncheckReturnToOriginModeSwitch) { - const redirectToOriginCheckboxExists = await testSubjects.exists( - 'returnToOriginModeSwitch' - ); - if (!redirectToOriginCheckboxExists) { - throw new Error('Unable to uncheck "returnToOriginModeSwitch", it does not exist.'); - } - await testSubjects.setEuiSwitch('returnToOriginModeSwitch', 'uncheck'); - } + await PageObjects.visualize.setSaveModalValues(name, { + addToDashboard: false, + redirectToOrigin, + saveAsNew: true, + }); if (tags) { await testSubjects.click('savedObjectTagSelector'); for (const tagName of tags) { diff --git a/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts b/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts index 4e44659b4fc67..32b9cc378db45 100644 --- a/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts +++ b/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts @@ -13,7 +13,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const listingTable = getService('listingTable'); const testSubjects = getService('testSubjects'); const find = getService('find'); - const PageObjects = getPageObjects(['maps', 'tagManagement', 'common']); + const PageObjects = getPageObjects(['maps', 'tagManagement', 'common', 'visualize']); /** * Select tags in the searchbar's tag filter. @@ -78,7 +78,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('allows to select tags for a new map', async () => { - await PageObjects.maps.saveMap('my-new-map', false, ['tag-1', 'tag-3']); + await PageObjects.maps.saveMap('my-new-map', true, ['tag-1', 'tag-3']); await PageObjects.maps.gotoMapListingPage(); await selectFilterTags('tag-1'); @@ -91,6 +91,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await testSubjects.click('mapSaveButton'); await testSubjects.setValue('savedObjectTitle', 'map-with-new-tag'); + await PageObjects.visualize.setSaveModalValues('map-with-new-tag', { + addToDashboard: false, + saveAsNew: true, + }); await testSubjects.click('savedObjectTagSelector'); await testSubjects.click(`tagSelectorOption-action__create`); @@ -127,7 +131,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('allows to select tags for an existing map', async () => { await listingTable.clickItemLink('map', 'map 4 (tag-1)'); - await PageObjects.maps.saveMap('map 4 (tag-1)', false, ['tag-3']); + await PageObjects.maps.saveMap('map 4 (tag-1)', true, ['tag-3']); await PageObjects.maps.gotoMapListingPage(); await selectFilterTags('tag-3'); From eaf6831022991d17629c274aa2d11d8e0a1594db Mon Sep 17 00:00:00 2001 From: Michail Yasonik Date: Tue, 26 Jan 2021 12:48:22 -0500 Subject: [PATCH 21/21] Adding better aria-labels for global search and field search in Lens (#89215) --- .../public/components/__snapshots__/search_bar.test.tsx.snap | 2 +- .../global_search_bar/public/components/search_bar.tsx | 3 +++ .../lens/public/indexpattern_datasource/datapanel.tsx | 5 +++-- x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap index f5e7a030d59e3..8433d98c232d6 100644 --- a/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap +++ b/x-pack/plugins/global_search_bar/public/components/__snapshots__/search_bar.test.tsx.snap @@ -33,7 +33,7 @@ exports[`SearchBar supports keyboard shortcuts 1`] = ` { setLocalState({ ...localState, nameFilter: e.target.value }); }} - aria-label={i18n.translate('xpack.lens.indexPatterns.filterByNameAriaLabel', { - defaultMessage: 'Search fields', + aria-label={i18n.translate('xpack.lens.indexPatterns.filterByNameLabel', { + defaultMessage: 'Search field names', + description: 'Search the list of fields in the index pattern for the provided text', })} aria-describedby={fieldSearchDescriptionId} /> diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 93267c950c10e..e28b41e0ce5e3 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -11431,7 +11431,6 @@ "xpack.lens.indexPatterns.clearFiltersLabel": "名前とタイプフィルターを消去", "xpack.lens.indexPatterns.fieldFiltersLabel": "フィールドフィルター", "xpack.lens.indexPatterns.fieldSearchLiveRegion": "{availableFields}使用可能な{availableFields, plural, other {フィールド}}。{emptyFields}空の{emptyFields, plural, other {フィールド}}。 {metaFields}メタ{metaFields, plural, other {フィールド}}。", - "xpack.lens.indexPatterns.filterByNameAriaLabel": "検索フィールド", "xpack.lens.indexPatterns.filterByNameLabel": "検索フィールド名", "xpack.lens.indexPatterns.noAvailableDataLabel": "データを含むフィールドはありません。", "xpack.lens.indexPatterns.noDataLabel": "フィールドがありません。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 41bdf97333dd7..49fd9ce095f66 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -11460,7 +11460,6 @@ "xpack.lens.indexPatterns.clearFiltersLabel": "清除名称和类型筛选", "xpack.lens.indexPatterns.fieldFiltersLabel": "字段筛选", "xpack.lens.indexPatterns.fieldSearchLiveRegion": "{availableFields} 个可用{availableFields, plural, other {字段}}。{emptyFields} 个空{emptyFields, plural, other {字段}}。{metaFields} 个元{metaFields, plural,other {字段}}。", - "xpack.lens.indexPatterns.filterByNameAriaLabel": "搜索字段", "xpack.lens.indexPatterns.filterByNameLabel": "搜索字段名称", "xpack.lens.indexPatterns.noAvailableDataLabel": "没有包含数据的可用字段。", "xpack.lens.indexPatterns.noDataLabel": "无字段。",