From 4efd26a995674f8a25c8bb688bd19ecf92d47773 Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Fri, 7 Feb 2020 10:23:27 +0100 Subject: [PATCH 1/4] Retry ES API calls that fail with 410/Gone (#56950) Co-authored-by: Elastic Machine --- src/core/server/elasticsearch/retry_call_cluster.test.ts | 1 + src/core/server/elasticsearch/retry_call_cluster.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/server/elasticsearch/retry_call_cluster.test.ts b/src/core/server/elasticsearch/retry_call_cluster.test.ts index 275bda17ab92f..b5a5185ab39d9 100644 --- a/src/core/server/elasticsearch/retry_call_cluster.test.ts +++ b/src/core/server/elasticsearch/retry_call_cluster.test.ts @@ -66,6 +66,7 @@ describe('migrationsRetryCallCluster', () => { 'RequestTimeout', 'AuthenticationException', 'AuthorizationException', + 'Gone', ]; const mockLogger = loggingServiceMock.create(); diff --git a/src/core/server/elasticsearch/retry_call_cluster.ts b/src/core/server/elasticsearch/retry_call_cluster.ts index bd72ecf726461..ea3cc0b90c077 100644 --- a/src/core/server/elasticsearch/retry_call_cluster.ts +++ b/src/core/server/elasticsearch/retry_call_cluster.ts @@ -62,7 +62,9 @@ export function migrationsRetryCallCluster( error instanceof esErrors.ServiceUnavailable || error instanceof esErrors.RequestTimeout || error instanceof esErrors.AuthenticationException || - error instanceof esErrors.AuthorizationException + error instanceof esErrors.AuthorizationException || + // @ts-ignore + error instanceof esErrors.Gone ); }, timer(delay), From c4fe6ece507238cfe4b8b1ab40b4906fa60142ec Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Fri, 7 Feb 2020 10:48:34 +0100 Subject: [PATCH 2/4] Kibana app migration: Move static code dependencies into kibana_legacy plugin, part 1 (#56408) * Migrate PromiseServiceCreator * Migrate migrateLegacyQuery * Migrate watch_multi decorator * Migrate call_after_bindings_workaround * Migrate configureAppAngularModule, ensureDefaultIndexPattern and deps * Migrate kbn_accessible_clicks * Migrate PrivateProvider * Migrate registerListenEventListener * Adapt i18n files --- .i18nrc.json | 1 + .../kibana/public/dashboard/legacy_imports.ts | 16 +- .../public/discover/get_inner_angular.ts | 21 +- .../kibana/public/discover/kibana_services.ts | 13 +- .../call_after_bindings_workaround.js} | 20 -- .../discover/np_ready/angular/context_app.js | 3 +- .../doc_viewer/doc_viewer_render_error.tsx | 4 +- .../components/doc_viewer/doc_viewer_tab.tsx | 4 +- .../core_plugins/kibana/public/home/index.ts | 2 +- .../kibana/public/visualize/legacy_imports.ts | 18 +- .../vis_type_table/public/legacy_imports.ts | 16 +- src/legacy/ui/public/UI_SYSTEMS.md | 2 +- .../accessibility/kbn_accessible_click.js | 53 +---- .../ui/public/directives/listen/listen.js | 19 +- .../ui/public/directives/watch_multi/index.js | 4 +- .../error_url_overflow/__tests__/ie_regex.js | 2 +- .../error_url_overflow/error_url_overflow.js | 4 +- .../ui/public/error_url_overflow/index.js | 2 +- .../ui/public/legacy_compat/__tests__/xsrf.js | 2 +- src/legacy/ui/public/legacy_compat/index.ts | 6 +- .../notify/banners/{index.js => index.ts} | 0 src/legacy/ui/public/notify/fatal_error.ts | 2 +- src/legacy/ui/public/notify/index.d.ts | 2 +- src/legacy/ui/public/notify/index.js | 2 +- src/legacy/ui/public/notify/toasts/index.ts | 3 +- .../notify/toasts/toast_notifications.ts | 41 +--- src/legacy/ui/public/notify/toasts/toasts.ts | 1 - src/legacy/ui/public/private/index.d.ts | 2 +- src/legacy/ui/public/private/private.js | 191 +--------------- .../promises/{promises.d.ts => index.ts} | 13 +- .../helpers/parse_search_source.ts | 2 +- .../public/system_api/__tests__/system_api.js | 5 +- src/legacy/ui/public/system_api/index.js | 2 +- .../public/angular}/angular_config.tsx | 55 +++-- .../angular}/ensure_default_index_pattern.tsx | 2 +- .../kibana_legacy/public/angular/index.ts} | 11 +- .../kibana_legacy/public/angular}/promises.js | 7 - .../public/angular}/watch_multi.js | 3 - src/plugins/kibana_legacy/public/index.ts | 3 + .../kibana_legacy/public/notify/index.ts} | 4 +- .../notify/lib/format_angular_http_error.ts | 4 +- .../public/notify/lib/format_es_msg.test.js | 0 .../public/notify/lib/format_es_msg.ts} | 9 +- .../public/notify/lib/format_msg.test.js | 0 .../public/notify/lib/format_msg.ts} | 8 +- .../public/notify/lib/format_stack.ts} | 6 +- .../kibana_legacy/public/notify/lib/index.ts} | 6 +- .../notify/toasts/TOAST_NOTIFICATIONS.md | 0 .../public/notify/toasts/index.ts} | 3 +- .../notify/toasts/toast_notifications.test.ts | 2 +- .../notify/toasts/toast_notifications.ts | 48 ++++ .../kibana_legacy/public/utils/index.ts} | 21 +- .../public/utils/kbn_accessible_click.js | 70 ++++++ .../public/utils/migrate_legacy_query.ts | 0 .../kibana_legacy/public/utils}/private.d.ts | 0 .../kibana_legacy/public/utils/private.js | 208 ++++++++++++++++++ .../utils/register_listen_event_listener.js | 35 +++ .../kibana_legacy/public/utils/system_api.ts} | 9 +- .../public/utils/url_overflow_service.ts} | 14 +- x-pack/legacy/plugins/canvas/public/legacy.ts | 2 +- .../plugins/graph/public/legacy_imports.ts | 2 +- .../public/lib/ajax_error_handler.tsx | 2 +- .../translations/translations/ja-JP.json | 18 +- .../translations/translations/zh-CN.json | 18 +- 64 files changed, 555 insertions(+), 493 deletions(-) rename src/legacy/{ui/public/compat/init_after_bindings_workaround.js => core_plugins/kibana/public/discover/np_ready/angular/context/helpers/call_after_bindings_workaround.js} (80%) rename src/legacy/ui/public/notify/banners/{index.js => index.ts} (100%) rename src/legacy/ui/public/promises/{promises.d.ts => index.ts} (68%) rename src/{legacy/ui/public/legacy_compat => plugins/kibana_legacy/public/angular}/angular_config.tsx (89%) rename src/{legacy/ui/public/legacy_compat => plugins/kibana_legacy/public/angular}/ensure_default_index_pattern.tsx (97%) rename src/{legacy/ui/public/compat/index.js => plugins/kibana_legacy/public/angular/index.ts} (76%) rename src/{legacy/ui/public/promises => plugins/kibana_legacy/public/angular}/promises.js (94%) rename src/{legacy/ui/public/directives/watch_multi => plugins/kibana_legacy/public/angular}/watch_multi.js (97%) rename src/{legacy/ui/public/promises/index.d.ts => plugins/kibana_legacy/public/notify/index.ts} (94%) rename src/{legacy/ui => plugins/kibana_legacy}/public/notify/lib/format_angular_http_error.ts (91%) rename src/{legacy/ui => plugins/kibana_legacy}/public/notify/lib/format_es_msg.test.js (100%) rename src/{legacy/ui/public/notify/lib/format_es_msg.js => plugins/kibana_legacy/public/notify/lib/format_es_msg.ts} (78%) rename src/{legacy/ui => plugins/kibana_legacy}/public/notify/lib/format_msg.test.js (100%) rename src/{legacy/ui/public/notify/lib/format_msg.js => plugins/kibana_legacy/public/notify/lib/format_msg.ts} (88%) rename src/{legacy/ui/public/notify/lib/format_stack.js => plugins/kibana_legacy/public/notify/lib/format_stack.ts} (85%) rename src/{legacy/ui/public/notify/lib/index.js => plugins/kibana_legacy/public/notify/lib/index.ts} (89%) rename src/{legacy/ui => plugins/kibana_legacy}/public/notify/toasts/TOAST_NOTIFICATIONS.md (100%) rename src/{legacy/ui/public/promises/index.js => plugins/kibana_legacy/public/notify/toasts/index.ts} (93%) rename src/{legacy/ui => plugins/kibana_legacy}/public/notify/toasts/toast_notifications.test.ts (98%) create mode 100644 src/plugins/kibana_legacy/public/notify/toasts/toast_notifications.ts rename src/{legacy/ui/public/notify/filters/markdown.js => plugins/kibana_legacy/public/utils/index.ts} (69%) create mode 100644 src/plugins/kibana_legacy/public/utils/kbn_accessible_click.js rename src/{legacy/ui => plugins/kibana_legacy}/public/utils/migrate_legacy_query.ts (100%) rename src/{legacy/ui/public/private => plugins/kibana_legacy/public/utils}/private.d.ts (100%) create mode 100644 src/plugins/kibana_legacy/public/utils/private.js create mode 100644 src/plugins/kibana_legacy/public/utils/register_listen_event_listener.js rename src/{legacy/ui/public/system_api/system_api.js => plugins/kibana_legacy/public/utils/system_api.ts} (83%) rename src/{legacy/ui/public/error_url_overflow/url_overflow_service.js => plugins/kibana_legacy/public/utils/url_overflow_service.ts} (87%) diff --git a/.i18nrc.json b/.i18nrc.json index 08cf5a2823203..c171b842254ee 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -27,6 +27,7 @@ "src/plugins/management" ], "advancedSettings": "src/plugins/advanced_settings", + "kibana_legacy": "src/plugins/kibana_legacy", "kibana_react": "src/legacy/core_plugins/kibana_react", "kibana-react": "src/plugins/kibana_react", "kibana_utils": "src/plugins/kibana_utils", diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts index ff70ed9dc2eb7..b729691831e9a 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts @@ -29,26 +29,26 @@ import chrome from 'ui/chrome'; export const legacyChrome = chrome; export { SavedObjectSaveOpts } from 'ui/saved_objects/types'; export { npSetup, npStart } from 'ui/new_platform'; -export { IPrivate } from 'ui/private'; export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; // @ts-ignore export { ConfirmationButtonTypes } from 'ui/modals/confirm_modal'; -export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; export { KbnUrl } from 'ui/url/kbn_url'; // @ts-ignore -export { PrivateProvider } from 'ui/private/private'; -// @ts-ignore export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; // @ts-ignore -export { PromiseServiceCreator } from 'ui/promises/promises'; -// @ts-ignore export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url/index'; // @ts-ignore export { confirmModalFactory } from 'ui/modals/confirm_modal'; -export { configureAppAngularModule } from 'ui/legacy_compat'; -export { ensureDefaultIndexPattern } from 'ui/legacy_compat'; export { IInjector } from 'ui/chrome'; export { SavedObjectLoader } from 'ui/saved_objects'; export { VISUALIZE_EMBEDDABLE_TYPE } from '../../../visualizations/public/embeddable'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; +export { + configureAppAngularModule, + ensureDefaultIndexPattern, + IPrivate, + migrateLegacyQuery, + PrivateProvider, + PromiseServiceCreator, +} from '../../../../../plugins/kibana_legacy/public'; diff --git a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts index 36a6c8eaef40e..cc4dabd123ff4 100644 --- a/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts +++ b/src/legacy/core_plugins/kibana/public/discover/get_inner_angular.ts @@ -22,26 +22,15 @@ // They can stay even after NP cutover import angular from 'angular'; import 'ui/angular-bootstrap'; -import { IPrivate } from 'ui/private'; import { EuiIcon } from '@elastic/eui'; // @ts-ignore import { StateProvider } from 'ui/state_management/state'; // @ts-ignore import { EventsProvider } from 'ui/events'; import { PersistedState } from 'ui/persisted_state'; -// @ts-ignore -import { PromiseServiceCreator } from 'ui/promises/promises'; import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; -// @ts-ignore -import { PrivateProvider } from 'ui/private/private'; import { CoreStart, LegacyCoreStart, IUiSettingsClient } from 'kibana/public'; // @ts-ignore -import { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi'; -// @ts-ignore -import { registerListenEventListener } from 'ui/directives/listen/listen'; -// @ts-ignore -import { KbnAccessibleClickProvider } from 'ui/accessibility/kbn_accessible_click'; -// @ts-ignore import { AppStateProvider } from 'ui/state_management/app_state'; // @ts-ignore import { GlobalStateProvider } from 'ui/state_management/global_state'; @@ -51,7 +40,6 @@ import { StateManagementConfigProvider } from 'ui/state_management/config_provid import { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; // @ts-ignore import { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; -import { configureAppAngularModule } from 'ui/legacy_compat'; import { IndexPatterns, DataPublicPluginStart } from '../../../../../plugins/data/public'; import { Storage } from '../../../../../plugins/kibana_utils/public'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public'; @@ -82,6 +70,15 @@ import { FixedScrollProvider } from './np_ready/angular/directives/fixed_scroll' // @ts-ignore import { DebounceProviderTimeout } from './np_ready/angular/directives/debounce/debounce'; import { createRenderCompleteDirective } from './np_ready/angular/directives/render_complete'; +import { + configureAppAngularModule, + IPrivate, + KbnAccessibleClickProvider, + PrivateProvider, + PromiseServiceCreator, + registerListenEventListener, + watchMultiDecorator, +} from '../../../../../plugins/kibana_legacy/public'; /** * returns the main inner angular module, it contains all the parts of Angular Discover diff --git a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts index 820c9949342a4..b0bb17ce1ac7f 100644 --- a/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts +++ b/src/legacy/core_plugins/kibana/public/discover/kibana_services.ts @@ -51,23 +51,22 @@ export function setServices(newServices: any) { export { angular }; export { wrapInI18nContext } from 'ui/i18n'; export { buildVislibDimensions } from '../../../visualizations/public'; -// @ts-ignore -export { callAfterBindingsWorkaround } from 'ui/compat'; export { getRequestInspectorStats, getResponseInspectorStats } from '../../../data/public'; // @ts-ignore export { intervalOptions } from 'ui/agg_types'; -// @ts-ignore -export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; // @ts-ignore export { timezoneProvider } from 'ui/vis/lib/timezone'; // @ts-ignore export { tabifyAggResponse } from 'ui/agg_response/tabify'; -export { ensureDefaultIndexPattern } from 'ui/legacy_compat'; export { unhashUrl } from '../../../../../plugins/kibana_utils/public'; -// @ts-ignore -export { formatMsg, formatStack } from 'ui/notify/lib/index'; +export { + migrateLegacyQuery, + ensureDefaultIndexPattern, + formatMsg, + formatStack, +} from '../../../../../plugins/kibana_legacy/public'; // EXPORT types export { diff --git a/src/legacy/ui/public/compat/init_after_bindings_workaround.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/helpers/call_after_bindings_workaround.js similarity index 80% rename from src/legacy/ui/public/compat/init_after_bindings_workaround.js rename to src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/helpers/call_after_bindings_workaround.js index 7ba42d3b0476d..95a37f3d8e207 100644 --- a/src/legacy/ui/public/compat/init_after_bindings_workaround.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/helpers/call_after_bindings_workaround.js @@ -49,26 +49,6 @@ * */ -export class InitAfterBindingsWorkaround { - static $inject = ['$injector', '$attrs', '$element', '$scope', '$transclude']; - constructor($injector, $attrs, $element, $scope, $transclude) { - if (!this.initAfterBindings) { - throw new Error( - 'When using inheritance you must move the logic in the constructor to the `initAfterBindings` method' - ); - } - - this.$onInit = () => { - $injector.invoke(this.initAfterBindings, this, { - $attrs, - $element, - $scope, - $transclude, - }); - }; - } -} - export function callAfterBindingsWorkaround(constructor) { return function InitAfterBindingsWrapper($injector, $attrs, $element, $scope, $transclude) { this.$onInit = () => { diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context_app.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context_app.js index 6549f13556373..b5ba2844e8b06 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context_app.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context_app.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; -import { callAfterBindingsWorkaround, getAngularModule } from '../../kibana_services'; +import { getAngularModule } from '../../kibana_services'; import contextAppTemplate from './context_app.html'; import './context/components/action_bar'; import { getFirstSortableField } from './context/api/utils/sorting'; @@ -33,6 +33,7 @@ import { LOADING_STATUS, QueryActionsProvider, } from './context/query'; +import { callAfterBindingsWorkaround } from './context/helpers/call_after_bindings_workaround'; const module = getAngularModule(); diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_error.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_error.tsx index 201ed562cfd6f..075217add7b52 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_error.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_render_error.tsx @@ -21,12 +21,12 @@ import { EuiCallOut, EuiCodeBlock } from '@elastic/eui'; import { formatMsg, formatStack } from '../../../kibana_services'; interface Props { - error: Error | string | null; + error: Error | string; } export function DocViewerError({ error }: Props) { const errMsg = formatMsg(error); - const errStack = error ? formatStack(error) : ''; + const errStack = typeof error === 'object' ? formatStack(error) : ''; return ( diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_tab.tsx b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_tab.tsx index 0c21fafc91d69..2dfee3487af8c 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_tab.tsx +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/components/doc_viewer/doc_viewer_tab.tsx @@ -31,7 +31,7 @@ interface Props { } interface State { - error: null | Error | string; + error: Error | string; hasError: boolean; } /** @@ -42,7 +42,7 @@ interface State { export class DocViewerTab extends React.Component { state = { hasError: false, - error: null, + error: '', }; static getDerivedStateFromError(error: unknown) { diff --git a/src/legacy/core_plugins/kibana/public/home/index.ts b/src/legacy/core_plugins/kibana/public/home/index.ts index 27d09a53ba20d..f02ec234e0a83 100644 --- a/src/legacy/core_plugins/kibana/public/home/index.ts +++ b/src/legacy/core_plugins/kibana/public/home/index.ts @@ -20,9 +20,9 @@ import { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue'; import { npSetup, npStart } from 'ui/new_platform'; import chrome from 'ui/chrome'; -import { IPrivate } from 'ui/private'; import { HomePlugin, LegacyAngularInjectedDependencies } from './plugin'; import { TelemetryOptInProvider } from '../../../telemetry/public/services'; +import { IPrivate } from '../../../../../plugins/kibana_legacy/public'; /** * Get dependencies relying on the global angular context. diff --git a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts index bb24870c5a5f3..d3a7f6ac1ff7d 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/legacy_imports.ts @@ -40,31 +40,29 @@ export { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; export { PersistedState } from 'ui/persisted_state'; export { npSetup, npStart } from 'ui/new_platform'; -export { IPrivate } from 'ui/private'; -// @ts-ignore -export { PrivateProvider } from 'ui/private/private'; export { subscribeWithScope } from 'ui/utils/subscribe_with_scope'; -export { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; // @ts-ignore export { EventsProvider } from 'ui/events'; // @ts-ignore export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; // @ts-ignore -export { PromiseServiceCreator } from 'ui/promises/promises'; -// @ts-ignore export { confirmModalFactory } from 'ui/modals/confirm_modal'; -export { configureAppAngularModule, ensureDefaultIndexPattern } from 'ui/legacy_compat'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; - // @ts-ignore export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url'; export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url'; - export { wrapInI18nContext } from 'ui/i18n'; - export { DashboardConstants } from '../dashboard/np_ready/dashboard_constants'; export { VisSavedObject } from '../../../visualizations/public/embeddable/visualize_embeddable'; export { VISUALIZE_EMBEDDABLE_TYPE } from '../../../visualizations/public/embeddable'; export { VisType } from '../../../visualizations/public'; +export { + configureAppAngularModule, + ensureDefaultIndexPattern, + IPrivate, + migrateLegacyQuery, + PrivateProvider, + PromiseServiceCreator, +} from '../../../../../plugins/kibana_legacy/public'; diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts index efa6c0029e6d1..ed0a09e139b09 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts @@ -20,22 +20,18 @@ export { npSetup, npStart } from 'ui/new_platform'; export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; export { IAggConfig, AggGroupNames, Schemas } from 'ui/agg_types'; - -// @ts-ignore -export { PrivateProvider } from 'ui/private/private'; // @ts-ignore export { PaginateDirectiveProvider } from 'ui/directives/paginate'; // @ts-ignore export { PaginateControlsDirectiveProvider } from 'ui/directives/paginate'; // @ts-ignore -export { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi'; - -// @ts-ignore -export { KbnAccessibleClickProvider } from 'ui/accessibility/kbn_accessible_click'; -// @ts-ignore export { StateManagementConfigProvider } from 'ui/state_management/config_provider'; -export { configureAppAngularModule } from 'ui/legacy_compat'; - export { tabifyGetColumns } from 'ui/agg_response/tabify/_get_columns'; // @ts-ignore export { tabifyAggResponse } from 'ui/agg_response/tabify'; +export { + configureAppAngularModule, + KbnAccessibleClickProvider, + PrivateProvider, + watchMultiDecorator, +} from '../../../../plugins/kibana_legacy/public'; diff --git a/src/legacy/ui/public/UI_SYSTEMS.md b/src/legacy/ui/public/UI_SYSTEMS.md index 37bfbcf92f640..8462b2c8f4144 100644 --- a/src/legacy/ui/public/UI_SYSTEMS.md +++ b/src/legacy/ui/public/UI_SYSTEMS.md @@ -5,4 +5,4 @@ In this directory you'll find various UI systems you can use to craft effective ## ui/notify * [banners](notify/banners/BANNERS.md) -* [toastNotifications](notify/toasts/TOAST_NOTIFICATIONS.md) +* [toastNotifications](../../../plugins/kibana_legacy/public/notify/toasts/TOAST_NOTIFICATIONS.md) diff --git a/src/legacy/ui/public/accessibility/kbn_accessible_click.js b/src/legacy/ui/public/accessibility/kbn_accessible_click.js index 35a2fa56af169..a57fbc6be82fd 100644 --- a/src/legacy/ui/public/accessibility/kbn_accessible_click.js +++ b/src/legacy/ui/public/accessibility/kbn_accessible_click.js @@ -37,58 +37,7 @@ * Apply this directive to any of these elements to automatically do the above. */ -import { accessibleClickKeys, keyCodes } from '@elastic/eui'; import { uiModules } from '../modules'; - -export function KbnAccessibleClickProvider() { - return { - restrict: 'A', - controller: $element => { - $element.on('keydown', e => { - // Prevent a scroll from occurring if the user has hit space. - if (e.keyCode === keyCodes.SPACE) { - e.preventDefault(); - } - }); - }, - link: (scope, element, attrs) => { - // The whole point of this directive is to hack in functionality that native buttons provide - // by default. - const elementType = element.prop('tagName'); - - if (elementType === 'BUTTON') { - throw new Error(`kbnAccessibleClick doesn't need to be used on a button.`); - } - - if (elementType === 'A' && attrs.href !== undefined) { - throw new Error( - `kbnAccessibleClick doesn't need to be used on a link if it has a href attribute.` - ); - } - - // We're emulating a click action, so we should already have a regular click handler defined. - if (!attrs.ngClick) { - throw new Error('kbnAccessibleClick requires ng-click to be defined on its element.'); - } - - // If the developer hasn't already specified attributes required for accessibility, add them. - if (attrs.tabindex === undefined) { - element.attr('tabindex', '0'); - } - - if (attrs.role === undefined) { - element.attr('role', 'button'); - } - - element.on('keyup', e => { - // Support keyboard accessibility by emulating mouse click on ENTER or SPACE keypress. - if (accessibleClickKeys[e.keyCode]) { - // Delegate to the click handler on the element (assumed to be ng-click). - element.click(); - } - }); - }, - }; -} +import { KbnAccessibleClickProvider } from '../../../../plugins/kibana_legacy/public'; uiModules.get('kibana').directive('kbnAccessibleClick', KbnAccessibleClickProvider); diff --git a/src/legacy/ui/public/directives/listen/listen.js b/src/legacy/ui/public/directives/listen/listen.js index 97185e4f602ff..db19471fdb640 100644 --- a/src/legacy/ui/public/directives/listen/listen.js +++ b/src/legacy/ui/public/directives/listen/listen.js @@ -18,23 +18,6 @@ */ import { uiModules } from '../../modules'; - -export function registerListenEventListener($rootScope) { - /** - * Helper that registers an event listener, and removes that listener when - * the $scope is destroyed. - * - * @param {SimpleEmitter} emitter - the event emitter to listen to - * @param {string} eventName - the event name - * @param {Function} handler - the event handler - * @return {undefined} - */ - $rootScope.constructor.prototype.$listen = function(emitter, eventName, handler) { - emitter.on(eventName, handler); - this.$on('$destroy', function() { - emitter.off(eventName, handler); - }); - }; -} +import { registerListenEventListener } from '../../../../../plugins/kibana_legacy/public'; uiModules.get('kibana').run(registerListenEventListener); diff --git a/src/legacy/ui/public/directives/watch_multi/index.js b/src/legacy/ui/public/directives/watch_multi/index.js index 3f0f43ce27ed2..800bb503088d4 100644 --- a/src/legacy/ui/public/directives/watch_multi/index.js +++ b/src/legacy/ui/public/directives/watch_multi/index.js @@ -17,4 +17,6 @@ * under the License. */ -import './watch_multi'; +import { uiModules } from '../../modules'; +import { watchMultiDecorator } from '../../../../../plugins/kibana_legacy/public'; +uiModules.get('kibana').config(watchMultiDecorator); diff --git a/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js b/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js index 3f5a3442b47b3..3d770c13a81aa 100644 --- a/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js +++ b/src/legacy/ui/public/error_url_overflow/__tests__/ie_regex.js @@ -18,7 +18,7 @@ */ import expect from '@kbn/expect'; -import { IE_REGEX } from '../url_overflow_service.js'; +import { IE_REGEX } from '../../../../../plugins/kibana_legacy/public'; describe('IE_REGEX', () => { it('should detect IE 9', () => { diff --git a/src/legacy/ui/public/error_url_overflow/error_url_overflow.js b/src/legacy/ui/public/error_url_overflow/error_url_overflow.js index c9b20f41d2b99..223b81fa36fde 100644 --- a/src/legacy/ui/public/error_url_overflow/error_url_overflow.js +++ b/src/legacy/ui/public/error_url_overflow/error_url_overflow.js @@ -22,9 +22,9 @@ import uiRoutes from '../routes'; import { KbnUrlProvider } from '../url'; import template from './error_url_overflow.html'; -import { UrlOverflowService } from './url_overflow_service'; +import { UrlOverflowService } from '../../../../plugins/kibana_legacy/public'; -export * from './url_overflow_service'; +export { UrlOverflowService }; uiRoutes.when('/error/url-overflow', { template, diff --git a/src/legacy/ui/public/error_url_overflow/index.js b/src/legacy/ui/public/error_url_overflow/index.js index c5b13182a8288..06a98789349f8 100644 --- a/src/legacy/ui/public/error_url_overflow/index.js +++ b/src/legacy/ui/public/error_url_overflow/index.js @@ -18,4 +18,4 @@ */ import './error_url_overflow'; -export { UrlOverflowService } from './url_overflow_service'; +export { UrlOverflowService } from '../../../../plugins/kibana_legacy/public'; diff --git a/src/legacy/ui/public/legacy_compat/__tests__/xsrf.js b/src/legacy/ui/public/legacy_compat/__tests__/xsrf.js index 6d2fd2318686a..fc12a18d72823 100644 --- a/src/legacy/ui/public/legacy_compat/__tests__/xsrf.js +++ b/src/legacy/ui/public/legacy_compat/__tests__/xsrf.js @@ -22,7 +22,7 @@ import expect from '@kbn/expect'; import sinon from 'sinon'; import ngMock from 'ng_mock'; -import { $setupXsrfRequestInterceptor } from '../angular_config'; +import { $setupXsrfRequestInterceptor } from '../../../../../plugins/kibana_legacy/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { version } from '../../../../../core/server/utils/package_json'; diff --git a/src/legacy/ui/public/legacy_compat/index.ts b/src/legacy/ui/public/legacy_compat/index.ts index ea8932114118e..3b700c8d59399 100644 --- a/src/legacy/ui/public/legacy_compat/index.ts +++ b/src/legacy/ui/public/legacy_compat/index.ts @@ -17,5 +17,7 @@ * under the License. */ -export { configureAppAngularModule } from './angular_config'; -export { ensureDefaultIndexPattern } from './ensure_default_index_pattern'; +export { + configureAppAngularModule, + ensureDefaultIndexPattern, +} from '../../../../plugins/kibana_legacy/public'; diff --git a/src/legacy/ui/public/notify/banners/index.js b/src/legacy/ui/public/notify/banners/index.ts similarity index 100% rename from src/legacy/ui/public/notify/banners/index.js rename to src/legacy/ui/public/notify/banners/index.ts diff --git a/src/legacy/ui/public/notify/fatal_error.ts b/src/legacy/ui/public/notify/fatal_error.ts index 4c02322bae492..7fa2ae7ac6fe6 100644 --- a/src/legacy/ui/public/notify/fatal_error.ts +++ b/src/legacy/ui/public/notify/fatal_error.ts @@ -22,7 +22,7 @@ import { AngularHttpError, formatAngularHttpError, isAngularHttpError, -} from './lib/format_angular_http_error'; +} from '../../../../plugins/kibana_legacy/public'; export function addFatalErrorCallback(callback: () => void) { npSetup.core.fatalErrors.get$().subscribe(() => { diff --git a/src/legacy/ui/public/notify/index.d.ts b/src/legacy/ui/public/notify/index.d.ts index c76924eb25819..3c1a7ba02db72 100644 --- a/src/legacy/ui/public/notify/index.d.ts +++ b/src/legacy/ui/public/notify/index.d.ts @@ -17,5 +17,5 @@ * under the License. */ -export { toastNotifications, Toast, ToastInput } from './toasts'; +export { toastNotifications } from './toasts'; export { fatalError } from './fatal_error'; diff --git a/src/legacy/ui/public/notify/index.js b/src/legacy/ui/public/notify/index.js index 70e6c635d43b9..f7526f3b8f8fd 100644 --- a/src/legacy/ui/public/notify/index.js +++ b/src/legacy/ui/public/notify/index.js @@ -19,5 +19,5 @@ export { fatalError, addFatalErrorCallback } from './fatal_error'; export { toastNotifications } from './toasts'; -export { banners } from './banners'; export { addAppRedirectMessageToUrl, showAppRedirectNotification } from './app_redirect'; +export { banners } from './banners'; diff --git a/src/legacy/ui/public/notify/toasts/index.ts b/src/legacy/ui/public/notify/toasts/index.ts index d305b176e1128..c5e8e3b7ca7a3 100644 --- a/src/legacy/ui/public/notify/toasts/index.ts +++ b/src/legacy/ui/public/notify/toasts/index.ts @@ -16,6 +16,5 @@ * specific language governing permissions and limitations * under the License. */ - +export { ToastNotifications } from './toast_notifications'; export { toastNotifications } from './toasts'; -export { Toast, ToastInput } from './toast_notifications'; diff --git a/src/legacy/ui/public/notify/toasts/toast_notifications.ts b/src/legacy/ui/public/notify/toasts/toast_notifications.ts index 987717ab17d39..d3ec8edb5d73a 100644 --- a/src/legacy/ui/public/notify/toasts/toast_notifications.ts +++ b/src/legacy/ui/public/notify/toasts/toast_notifications.ts @@ -16,40 +16,7 @@ * specific language governing permissions and limitations * under the License. */ - -import { - ErrorToastOptions, - NotificationsSetup, - Toast, - ToastInput, -} from '../../../../../core/public'; - -export { Toast, ToastInput }; - -export class ToastNotifications { - public list: Toast[] = []; - - private onChangeCallback?: () => void; - - constructor(private readonly toasts: NotificationsSetup['toasts']) { - toasts.get$().subscribe(list => { - this.list = list; - - if (this.onChangeCallback) { - this.onChangeCallback(); - } - }); - } - - public onChange = (callback: () => void) => { - this.onChangeCallback = callback; - }; - - public add = (toastOrTitle: ToastInput) => this.toasts.add(toastOrTitle); - public remove = (toast: Toast) => this.toasts.remove(toast); - public addSuccess = (toastOrTitle: ToastInput) => this.toasts.addSuccess(toastOrTitle); - public addWarning = (toastOrTitle: ToastInput) => this.toasts.addWarning(toastOrTitle); - public addDanger = (toastOrTitle: ToastInput) => this.toasts.addDanger(toastOrTitle); - public addError = (error: Error, options: ErrorToastOptions) => - this.toasts.addError(error, options); -} +/** + * ToastNotifications is deprecated! Please use npSetup.core.notifications.toasts instead + */ +export { ToastNotifications } from '../../../../../plugins/kibana_legacy/public'; diff --git a/src/legacy/ui/public/notify/toasts/toasts.ts b/src/legacy/ui/public/notify/toasts/toasts.ts index 8889ee4a6d981..15be7a7891553 100644 --- a/src/legacy/ui/public/notify/toasts/toasts.ts +++ b/src/legacy/ui/public/notify/toasts/toasts.ts @@ -19,5 +19,4 @@ import { npSetup } from 'ui/new_platform'; import { ToastNotifications } from './toast_notifications'; - export const toastNotifications = new ToastNotifications(npSetup.core.notifications.toasts); diff --git a/src/legacy/ui/public/private/index.d.ts b/src/legacy/ui/public/private/index.d.ts index d814b31102d59..895dc63939311 100644 --- a/src/legacy/ui/public/private/index.d.ts +++ b/src/legacy/ui/public/private/index.d.ts @@ -17,4 +17,4 @@ * under the License. */ -export { IPrivate } from './private'; +export { IPrivate } from '../../../../plugins/kibana_legacy/public/utils/private'; diff --git a/src/legacy/ui/public/private/private.js b/src/legacy/ui/public/private/private.js index 05bd55f4e1bdf..7a0751959417e 100644 --- a/src/legacy/ui/public/private/private.js +++ b/src/legacy/ui/public/private/private.js @@ -17,196 +17,7 @@ * under the License. */ -import _ from 'lodash'; import { uiModules } from '../modules'; -/** - * # `Private()` - * Private module loader, used to merge angular and require js dependency styles - * by allowing a require.js module to export a single provider function that will - * create a value used within an angular application. This provider can declare - * angular dependencies by listing them as arguments, and can be require additional - * Private modules. - * - * ## Define a private module provider: - * ```js - * export default function PingProvider($http) { - * this.ping = function () { - * return $http.head('/health-check'); - * }; - * }; - * ``` - * - * ## Require a private module: - * ```js - * export default function ServerHealthProvider(Private, Promise) { - * let ping = Private(require('ui/ping')); - * return { - * check: Promise.method(function () { - * let attempts = 0; - * return (function attempt() { - * attempts += 1; - * return ping.ping() - * .catch(function (err) { - * if (attempts < 3) return attempt(); - * }) - * }()) - * .then(function () { - * return true; - * }) - * .catch(function () { - * return false; - * }); - * }) - * } - * }; - * ``` - * - * # `Private.stub(provider, newInstance)` - * `Private.stub()` replaces the instance of a module with another value. This is all we have needed until now. - * - * ```js - * beforeEach(inject(function ($injector, Private) { - * Private.stub( - * // since this module just exports a function, we need to change - * // what Private returns in order to modify it's behavior - * require('ui/agg_response/hierarchical/_build_split'), - * sinon.stub().returns(fakeSplit) - * ); - * })); - * ``` - * - * # `Private.swap(oldProvider, newProvider)` - * This new method does an 1-for-1 swap of module providers, unlike `stub()` which replaces a modules instance. - * Pass the module you want to swap out, and the one it should be replaced with, then profit. - * - * Note: even though this example shows `swap()` being called in a config - * function, it can be called from anywhere. It is particularly useful - * in this scenario though. - * - * ```js - * beforeEach(module('kibana', function (PrivateProvider) { - * PrivateProvider.swap( - * function StubbedRedirectProvider($decorate) { - * // $decorate is a function that will instantiate the original module when called - * return sinon.spy($decorate()); - * } - * ); - * })); - * ``` - * - * @param {[type]} prov [description] - */ - -const nextId = _.partial(_.uniqueId, 'privateProvider#'); - -function name(fn) { - return ( - fn.name || - fn - .toString() - .split('\n') - .shift() - ); -} - -export function PrivateProvider() { - const provider = this; - - // one cache/swaps per Provider - const cache = {}; - const swaps = {}; - - // return the uniq id for this function - function identify(fn) { - if (typeof fn !== 'function') { - throw new TypeError('Expected private module "' + fn + '" to be a function'); - } - - if (fn.$$id) return fn.$$id; - else return (fn.$$id = nextId()); - } - - provider.stub = function(fn, instance) { - cache[identify(fn)] = instance; - return instance; - }; - - provider.swap = function(fn, prov) { - const id = identify(fn); - swaps[id] = prov; - }; - - provider.$get = [ - '$injector', - function PrivateFactory($injector) { - // prevent circular deps by tracking where we came from - const privPath = []; - const pathToString = function() { - return privPath.map(name).join(' -> '); - }; - - // call a private provider and return the instance it creates - function instantiate(prov, locals) { - if (~privPath.indexOf(prov)) { - throw new Error( - 'Circular reference to "' + - name(prov) + - '"' + - ' found while resolving private deps: ' + - pathToString() - ); - } - - privPath.push(prov); - - const context = {}; - let instance = $injector.invoke(prov, context, locals); - if (!_.isObject(instance)) instance = context; - - privPath.pop(); - return instance; - } - - // retrieve an instance from cache or create and store on - function get(id, prov, $delegateId, $delegateProv) { - if (cache[id]) return cache[id]; - - let instance; - - if ($delegateId != null && $delegateProv != null) { - instance = instantiate(prov, { - $decorate: _.partial(get, $delegateId, $delegateProv), - }); - } else { - instance = instantiate(prov); - } - - return (cache[id] = instance); - } - - // main api, get the appropriate instance for a provider - function Private(prov) { - let id = identify(prov); - let $delegateId; - let $delegateProv; - - if (swaps[id]) { - $delegateId = id; - $delegateProv = prov; - - prov = swaps[$delegateId]; - id = identify(prov); - } - - return get(id, prov, $delegateId, $delegateProv); - } - - Private.stub = provider.stub; - Private.swap = provider.swap; - - return Private; - }, - ]; -} +import { PrivateProvider } from '../../../../plugins/kibana_legacy/public'; uiModules.get('kibana/private').provider('Private', PrivateProvider); diff --git a/src/legacy/ui/public/promises/promises.d.ts b/src/legacy/ui/public/promises/index.ts similarity index 68% rename from src/legacy/ui/public/promises/promises.d.ts rename to src/legacy/ui/public/promises/index.ts index 84d81b39ec37d..07bb2554c5eda 100644 --- a/src/legacy/ui/public/promises/promises.d.ts +++ b/src/legacy/ui/public/promises/index.ts @@ -17,9 +17,12 @@ * under the License. */ -export interface PromiseService { - resolve: (value: T | PromiseLike) => ng.IPromise; +import { PromiseServiceCreator } from '../../../../plugins/kibana_legacy/public'; +export { createDefer } from './defer'; +// @ts-ignore +import { uiModules } from '../modules'; - // TODO: add additional typing - [key: string]: any; -} +const module = uiModules.get('kibana'); +// Provides a tiny subset of the excellent API from +// bluebird, reimplemented using the $q service +module.service('Promise', PromiseServiceCreator); diff --git a/src/legacy/ui/public/saved_objects/helpers/parse_search_source.ts b/src/legacy/ui/public/saved_objects/helpers/parse_search_source.ts index 8c52b7cfa0dbf..b194420fc1cd0 100644 --- a/src/legacy/ui/public/saved_objects/helpers/parse_search_source.ts +++ b/src/legacy/ui/public/saved_objects/helpers/parse_search_source.ts @@ -17,7 +17,7 @@ * under the License. */ import _ from 'lodash'; -import { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; +import { migrateLegacyQuery } from '../../../../../plugins/kibana_legacy/public'; import { SavedObject } from '../types'; import { InvalidJSONProperty } from '../../../../../plugins/kibana_utils/public'; diff --git a/src/legacy/ui/public/system_api/__tests__/system_api.js b/src/legacy/ui/public/system_api/__tests__/system_api.js index 1bb8656502204..822edaa08fdd6 100644 --- a/src/legacy/ui/public/system_api/__tests__/system_api.js +++ b/src/legacy/ui/public/system_api/__tests__/system_api.js @@ -18,7 +18,10 @@ */ import expect from '@kbn/expect'; -import { addSystemApiHeader, isSystemApiRequest } from '../system_api'; +import { + addSystemApiHeader, + isSystemApiRequest, +} from '../../../../../plugins/kibana_legacy/public'; describe('system_api', () => { describe('#addSystemApiHeader', () => { diff --git a/src/legacy/ui/public/system_api/index.js b/src/legacy/ui/public/system_api/index.js index 61c5909395aef..6361c0ea6c69a 100644 --- a/src/legacy/ui/public/system_api/index.js +++ b/src/legacy/ui/public/system_api/index.js @@ -17,4 +17,4 @@ * under the License. */ -export { addSystemApiHeader, isSystemApiRequest } from './system_api'; +export { addSystemApiHeader, isSystemApiRequest } from '../../../../plugins/kibana_legacy/public'; diff --git a/src/legacy/ui/public/legacy_compat/angular_config.tsx b/src/plugins/kibana_legacy/public/angular/angular_config.tsx similarity index 89% rename from src/legacy/ui/public/legacy_compat/angular_config.tsx rename to src/plugins/kibana_legacy/public/angular/angular_config.tsx index 7002b1c365eff..9a33cff82ed63 100644 --- a/src/legacy/ui/public/legacy_compat/angular_config.tsx +++ b/src/plugins/kibana_legacy/public/angular/angular_config.tsx @@ -28,26 +28,34 @@ import { IRootScopeService, } from 'angular'; import $ from 'jquery'; -import _, { cloneDeep, forOwn, get, set } from 'lodash'; +import { cloneDeep, forOwn, get, set } from 'lodash'; import React, { Fragment } from 'react'; import * as Rx from 'rxjs'; +import { ChromeBreadcrumb } from 'kibana/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { CoreStart, LegacyCoreStart } from 'kibana/public'; - -import { fatalError } from 'ui/notify'; -import { RouteConfiguration } from 'ui/routes/route_manager'; -// @ts-ignore -import { modifyUrl } from 'ui/url'; -import { toMountPoint } from '../../../../plugins/kibana_react/public'; -// @ts-ignore -import { UrlOverflowService } from '../error_url_overflow'; -// @ts-ignore -import { isSystemApiRequest } from '../system_api'; +import { modifyUrl } from '../../../../core/utils'; +import { toMountPoint } from '../../../kibana_react/public'; +import { isSystemApiRequest, UrlOverflowService } from '../utils'; +import { formatAngularHttpError, isAngularHttpError } from '../notify/lib'; const URL_LIMIT_WARN_WITHIN = 1000; +export interface RouteConfiguration { + controller?: string | ((...args: any[]) => void); + redirectTo?: string; + resolveRedirectTo?: (...args: any[]) => void; + reloadOnSearch?: boolean; + reloadOnUrl?: boolean; + outerAngularWrapperRoute?: boolean; + resolve?: object; + template?: string; + k7Breadcrumbs?: (...args: any[]) => ChromeBreadcrumb[]; + requireUICapability?: string; +} + /** * Detects whether a given angular route is a dummy route that doesn't * require any action. There are two ways this can happen: @@ -91,7 +99,7 @@ export const configureAppAngularModule = ( .value('esUrl', getEsUrl(newPlatform)) .value('uiCapabilities', newPlatform.application.capabilities) .config(setupCompileProvider(newPlatform)) - .config(setupLocationProvider(newPlatform)) + .config(setupLocationProvider()) .config($setupXsrfRequestInterceptor(newPlatform)) .run(capture$httpLoadingCount(newPlatform)) .run($setupBreadcrumbsAutoClear(newPlatform, isLocalAngular)) @@ -122,9 +130,7 @@ const setupCompileProvider = (newPlatform: LegacyCoreStart) => ( } }; -const setupLocationProvider = (newPlatform: CoreStart) => ( - $locationProvider: ILocationProvider -) => { +const setupLocationProvider = () => ($locationProvider: ILocationProvider) => { $locationProvider.html5Mode({ enabled: false, requireBase: false, @@ -165,9 +171,6 @@ export const $setupXsrfRequestInterceptor = (newPlatform: LegacyCoreStart) => { * and adds a root-level watcher that will capture the count of * active $http requests on each digest loop and expose the count to * the core.loadingCount api - * @param {Angular.Scope} $rootScope - * @param {HttpService} $http - * @return {undefined} */ const capture$httpLoadingCount = (newPlatform: CoreStart) => ( $rootScope: IRootScopeService, @@ -260,7 +263,10 @@ const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart, isLocalAngular: bool try { newPlatform.chrome.setBreadcrumbs($injector.invoke(k7BreadcrumbsProvider)); } catch (error) { - fatalError(error); + if (isAngularHttpError(error)) { + error = formatAngularHttpError(error); + } + newPlatform.fatalErrors.add(error, 'location'); } }); }; @@ -302,7 +308,10 @@ const $setupBadgeAutoClear = (newPlatform: CoreStart, isLocalAngular: boolean) = try { newPlatform.chrome.setBadge($injector.invoke(badgeProvider)); } catch (error) { - fatalError(error); + if (isAngularHttpError(error)) { + error = formatAngularHttpError(error); + } + newPlatform.fatalErrors.add(error, 'location'); } }); }; @@ -374,13 +383,13 @@ const $setupUrlOverflowHandling = (newPlatform: CoreStart, isLocalAngular: boole try { if (urlOverflow.check($location.absUrl()) <= URL_LIMIT_WARN_WITHIN) { newPlatform.notifications.toasts.addWarning({ - title: i18n.translate('common.ui.chrome.bigUrlWarningNotificationTitle', { + title: i18n.translate('kibana_legacy.bigUrlWarningNotificationTitle', { defaultMessage: 'The URL is big and Kibana might stop working', }), text: toMountPoint( diff --git a/src/legacy/ui/public/legacy_compat/ensure_default_index_pattern.tsx b/src/plugins/kibana_legacy/public/angular/ensure_default_index_pattern.tsx similarity index 97% rename from src/legacy/ui/public/legacy_compat/ensure_default_index_pattern.tsx rename to src/plugins/kibana_legacy/public/angular/ensure_default_index_pattern.tsx index bb6b9f805b413..1a3bb84ae7575 100644 --- a/src/legacy/ui/public/legacy_compat/ensure_default_index_pattern.tsx +++ b/src/plugins/kibana_legacy/public/angular/ensure_default_index_pattern.tsx @@ -79,7 +79,7 @@ export async function ensureDefaultIndexPattern( new KibanaLegacyPlugin(initializerContext); export * from './plugin'; +export * from './angular'; +export * from './notify'; +export * from './utils'; diff --git a/src/legacy/ui/public/promises/index.d.ts b/src/plugins/kibana_legacy/public/notify/index.ts similarity index 94% rename from src/legacy/ui/public/promises/index.d.ts rename to src/plugins/kibana_legacy/public/notify/index.ts index aa81770056cc1..6aa4e36ab7227 100644 --- a/src/legacy/ui/public/promises/index.d.ts +++ b/src/plugins/kibana_legacy/public/notify/index.ts @@ -16,5 +16,5 @@ * specific language governing permissions and limitations * under the License. */ - -export { PromiseService } from './promises'; +export * from './toasts'; +export * from './lib'; diff --git a/src/legacy/ui/public/notify/lib/format_angular_http_error.ts b/src/plugins/kibana_legacy/public/notify/lib/format_angular_http_error.ts similarity index 91% rename from src/legacy/ui/public/notify/lib/format_angular_http_error.ts rename to src/plugins/kibana_legacy/public/notify/lib/format_angular_http_error.ts index 1d3d0166cc2de..4436e2a156512 100644 --- a/src/legacy/ui/public/notify/lib/format_angular_http_error.ts +++ b/src/plugins/kibana_legacy/public/notify/lib/format_angular_http_error.ts @@ -36,7 +36,7 @@ export function formatAngularHttpError(error: AngularHttpError) { // is an Angular $http "error object" if (error.status === -1) { // status = -1 indicates that the request was failed to reach the server - return i18n.translate('common.ui.notify.fatalError.unavailableServerErrorMessage', { + return i18n.translate('kibana_legacy.notify.fatalError.unavailableServerErrorMessage', { defaultMessage: 'An HTTP request has failed to connect. ' + 'Please check if the Kibana server is running and that your browser has a working connection, ' + @@ -44,7 +44,7 @@ export function formatAngularHttpError(error: AngularHttpError) { }); } - return i18n.translate('common.ui.notify.fatalError.errorStatusMessage', { + return i18n.translate('kibana_legacy.notify.fatalError.errorStatusMessage', { defaultMessage: 'Error {errStatus} {errStatusText}: {errMessage}', values: { errStatus: error.status, diff --git a/src/legacy/ui/public/notify/lib/format_es_msg.test.js b/src/plugins/kibana_legacy/public/notify/lib/format_es_msg.test.js similarity index 100% rename from src/legacy/ui/public/notify/lib/format_es_msg.test.js rename to src/plugins/kibana_legacy/public/notify/lib/format_es_msg.test.js diff --git a/src/legacy/ui/public/notify/lib/format_es_msg.js b/src/plugins/kibana_legacy/public/notify/lib/format_es_msg.ts similarity index 78% rename from src/legacy/ui/public/notify/lib/format_es_msg.js rename to src/plugins/kibana_legacy/public/notify/lib/format_es_msg.ts index b591d1dfe114a..7305bec5348e5 100644 --- a/src/legacy/ui/public/notify/lib/format_es_msg.js +++ b/src/plugins/kibana_legacy/public/notify/lib/format_es_msg.ts @@ -19,20 +19,19 @@ import _ from 'lodash'; -const getRootCause = err => _.get(err, 'resp.error.root_cause'); +const getRootCause = (err: Record | string) => _.get(err, 'resp.error.root_cause'); /** * Utilize the extended error information returned from elasticsearch * @param {Error|String} err * @returns {string} */ -export const formatESMsg = err => { +export const formatESMsg = (err: Record | string) => { const rootCause = getRootCause(err); - if (!rootCause) { + if (!Array.isArray(rootCause)) { return; } - const result = _.pluck(rootCause, 'reason').join('\n'); - return result; + return rootCause.map((cause: Record) => cause.reason).join('\n'); }; diff --git a/src/legacy/ui/public/notify/lib/format_msg.test.js b/src/plugins/kibana_legacy/public/notify/lib/format_msg.test.js similarity index 100% rename from src/legacy/ui/public/notify/lib/format_msg.test.js rename to src/plugins/kibana_legacy/public/notify/lib/format_msg.test.js diff --git a/src/legacy/ui/public/notify/lib/format_msg.js b/src/plugins/kibana_legacy/public/notify/lib/format_msg.ts similarity index 88% rename from src/legacy/ui/public/notify/lib/format_msg.js rename to src/plugins/kibana_legacy/public/notify/lib/format_msg.ts index 09b0df5c818cf..8179c8f368b27 100644 --- a/src/legacy/ui/public/notify/lib/format_msg.js +++ b/src/plugins/kibana_legacy/public/notify/lib/format_msg.ts @@ -29,7 +29,7 @@ const has = _.has; * @param {String} source - Prefix for message indicating source (optional) * @returns {string} */ -export function formatMsg(err, source) { +export function formatMsg(err: Record | string, source: string = '') { let message = ''; if (source) { message += source + ': '; @@ -47,14 +47,14 @@ export function formatMsg(err, source) { // is an Angular $http "error object" if (err.status === -1) { // status = -1 indicates that the request was failed to reach the server - message += i18n.translate('common.ui.notify.toaster.unavailableServerErrorMessage', { + message += i18n.translate('kibana_legacy.notify.toaster.unavailableServerErrorMessage', { defaultMessage: 'An HTTP request has failed to connect. ' + 'Please check if the Kibana server is running and that your browser has a working connection, ' + 'or contact your system administrator.', }); } else { - message += i18n.translate('common.ui.notify.toaster.errorStatusMessage', { + message += i18n.translate('kibana_legacy.notify.toaster.errorStatusMessage', { defaultMessage: 'Error {errStatus} {errStatusText}: {errMessage}', values: { errStatus: err.status, @@ -68,7 +68,7 @@ export function formatMsg(err, source) { return message; } -formatMsg.describeError = function(err) { +formatMsg.describeError = function(err: Record) { if (!err) return undefined; if (err.shortMessage) return err.shortMessage; if (err.body && err.body.message) return err.body.message; diff --git a/src/legacy/ui/public/notify/lib/format_stack.js b/src/plugins/kibana_legacy/public/notify/lib/format_stack.ts similarity index 85% rename from src/legacy/ui/public/notify/lib/format_stack.js rename to src/plugins/kibana_legacy/public/notify/lib/format_stack.ts index 13a55228d61b9..472793e29bd50 100644 --- a/src/legacy/ui/public/notify/lib/format_stack.js +++ b/src/plugins/kibana_legacy/public/notify/lib/format_stack.ts @@ -20,9 +20,9 @@ import { i18n } from '@kbn/i18n'; // browsers format Error.stack differently; always include message -export function formatStack(err) { - if (err.stack && !~err.stack.indexOf(err.message)) { - return i18n.translate('common.ui.notify.toaster.errorMessage', { +export function formatStack(err: Record) { + if (err.stack && err.stack.indexOf(err.message) === -1) { + return i18n.translate('kibana_legacy.notify.toaster.errorMessage', { defaultMessage: `Error: {errorMessage} {errorStack}`, values: { diff --git a/src/legacy/ui/public/notify/lib/index.js b/src/plugins/kibana_legacy/public/notify/lib/index.ts similarity index 89% rename from src/legacy/ui/public/notify/lib/index.js rename to src/plugins/kibana_legacy/public/notify/lib/index.ts index 426cfbb88ed8d..c374b5926b64f 100644 --- a/src/legacy/ui/public/notify/lib/index.js +++ b/src/plugins/kibana_legacy/public/notify/lib/index.ts @@ -20,4 +20,8 @@ export { formatESMsg } from './format_es_msg'; export { formatMsg } from './format_msg'; export { formatStack } from './format_stack'; -export { isAngularHttpError, formatAngularHttpError } from './format_angular_http_error'; +export { + isAngularHttpError, + formatAngularHttpError, + AngularHttpError, +} from './format_angular_http_error'; diff --git a/src/legacy/ui/public/notify/toasts/TOAST_NOTIFICATIONS.md b/src/plugins/kibana_legacy/public/notify/toasts/TOAST_NOTIFICATIONS.md similarity index 100% rename from src/legacy/ui/public/notify/toasts/TOAST_NOTIFICATIONS.md rename to src/plugins/kibana_legacy/public/notify/toasts/TOAST_NOTIFICATIONS.md diff --git a/src/legacy/ui/public/promises/index.js b/src/plugins/kibana_legacy/public/notify/toasts/index.ts similarity index 93% rename from src/legacy/ui/public/promises/index.js rename to src/plugins/kibana_legacy/public/notify/toasts/index.ts index 88fe7520d4967..bcf5bbb64eaf7 100644 --- a/src/legacy/ui/public/promises/index.js +++ b/src/plugins/kibana_legacy/public/notify/toasts/index.ts @@ -17,5 +17,4 @@ * under the License. */ -import './promises'; -export { createDefer } from './defer'; +export { ToastNotifications } from './toast_notifications'; diff --git a/src/legacy/ui/public/notify/toasts/toast_notifications.test.ts b/src/plugins/kibana_legacy/public/notify/toasts/toast_notifications.test.ts similarity index 98% rename from src/legacy/ui/public/notify/toasts/toast_notifications.test.ts rename to src/plugins/kibana_legacy/public/notify/toasts/toast_notifications.test.ts index ba39ee59e388c..6b162a41a9d03 100644 --- a/src/legacy/ui/public/notify/toasts/toast_notifications.test.ts +++ b/src/plugins/kibana_legacy/public/notify/toasts/toast_notifications.test.ts @@ -19,7 +19,7 @@ import { notificationServiceMock } from '../../../../../core/public/mocks'; import { ToastNotifications } from './toast_notifications'; -import { Toast } from '../../../../../core/public'; +import { Toast } from 'kibana/public'; import { BehaviorSubject } from 'rxjs'; describe('ToastNotifications', () => { diff --git a/src/plugins/kibana_legacy/public/notify/toasts/toast_notifications.ts b/src/plugins/kibana_legacy/public/notify/toasts/toast_notifications.ts new file mode 100644 index 0000000000000..649e50c2d1d6f --- /dev/null +++ b/src/plugins/kibana_legacy/public/notify/toasts/toast_notifications.ts @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { NotificationsSetup, Toast, ToastInput, ErrorToastOptions } from 'kibana/public'; + +export class ToastNotifications { + public list: Toast[] = []; + + private onChangeCallback?: () => void; + + constructor(private readonly toasts: NotificationsSetup['toasts']) { + toasts.get$().subscribe(list => { + this.list = list; + + if (this.onChangeCallback) { + this.onChangeCallback(); + } + }); + } + + public onChange = (callback: () => void) => { + this.onChangeCallback = callback; + }; + + public add = (toastOrTitle: ToastInput) => this.toasts.add(toastOrTitle); + public remove = (toast: Toast) => this.toasts.remove(toast); + public addSuccess = (toastOrTitle: ToastInput) => this.toasts.addSuccess(toastOrTitle); + public addWarning = (toastOrTitle: ToastInput) => this.toasts.addWarning(toastOrTitle); + public addDanger = (toastOrTitle: ToastInput) => this.toasts.addDanger(toastOrTitle); + public addError = (error: Error, options: ErrorToastOptions) => + this.toasts.addError(error, options); +} diff --git a/src/legacy/ui/public/notify/filters/markdown.js b/src/plugins/kibana_legacy/public/utils/index.ts similarity index 69% rename from src/legacy/ui/public/notify/filters/markdown.js rename to src/plugins/kibana_legacy/public/utils/index.ts index 9ab7470b4a1c9..886ae0e877c38 100644 --- a/src/legacy/ui/public/notify/filters/markdown.js +++ b/src/plugins/kibana_legacy/public/utils/index.ts @@ -17,15 +17,12 @@ * under the License. */ -import MarkdownIt from 'markdown-it'; -import { uiModules } from 'ui/modules'; -import 'angular-sanitize'; - -const markdownIt = new MarkdownIt({ - html: false, - linkify: true, -}); - -uiModules.get('kibana', ['ngSanitize']).filter('markdown', function($sanitize) { - return md => (md ? $sanitize(markdownIt.render(md)) : ''); -}); +export * from './migrate_legacy_query'; +export * from './system_api'; +export * from './url_overflow_service'; +// @ts-ignore +export { KbnAccessibleClickProvider } from './kbn_accessible_click'; +// @ts-ignore +export { PrivateProvider, IPrivate } from './private'; +// @ts-ignore +export { registerListenEventListener } from './register_listen_event_listener'; diff --git a/src/plugins/kibana_legacy/public/utils/kbn_accessible_click.js b/src/plugins/kibana_legacy/public/utils/kbn_accessible_click.js new file mode 100644 index 0000000000000..26f41c9abac2b --- /dev/null +++ b/src/plugins/kibana_legacy/public/utils/kbn_accessible_click.js @@ -0,0 +1,70 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { accessibleClickKeys, keyCodes } from '@elastic/eui'; + +export function KbnAccessibleClickProvider() { + return { + restrict: 'A', + controller: $element => { + $element.on('keydown', e => { + // Prevent a scroll from occurring if the user has hit space. + if (e.keyCode === keyCodes.SPACE) { + e.preventDefault(); + } + }); + }, + link: (scope, element, attrs) => { + // The whole point of this directive is to hack in functionality that native buttons provide + // by default. + const elementType = element.prop('tagName'); + + if (elementType === 'BUTTON') { + throw new Error(`kbnAccessibleClick doesn't need to be used on a button.`); + } + + if (elementType === 'A' && attrs.href !== undefined) { + throw new Error( + `kbnAccessibleClick doesn't need to be used on a link if it has a href attribute.` + ); + } + + // We're emulating a click action, so we should already have a regular click handler defined. + if (!attrs.ngClick) { + throw new Error('kbnAccessibleClick requires ng-click to be defined on its element.'); + } + + // If the developer hasn't already specified attributes required for accessibility, add them. + if (attrs.tabindex === undefined) { + element.attr('tabindex', '0'); + } + + if (attrs.role === undefined) { + element.attr('role', 'button'); + } + + element.on('keyup', e => { + // Support keyboard accessibility by emulating mouse click on ENTER or SPACE keypress. + if (accessibleClickKeys[e.keyCode]) { + // Delegate to the click handler on the element (assumed to be ng-click). + element.click(); + } + }); + }, + }; +} diff --git a/src/legacy/ui/public/utils/migrate_legacy_query.ts b/src/plugins/kibana_legacy/public/utils/migrate_legacy_query.ts similarity index 100% rename from src/legacy/ui/public/utils/migrate_legacy_query.ts rename to src/plugins/kibana_legacy/public/utils/migrate_legacy_query.ts diff --git a/src/legacy/ui/public/private/private.d.ts b/src/plugins/kibana_legacy/public/utils/private.d.ts similarity index 100% rename from src/legacy/ui/public/private/private.d.ts rename to src/plugins/kibana_legacy/public/utils/private.d.ts diff --git a/src/plugins/kibana_legacy/public/utils/private.js b/src/plugins/kibana_legacy/public/utils/private.js new file mode 100644 index 0000000000000..18fdcb8c89215 --- /dev/null +++ b/src/plugins/kibana_legacy/public/utils/private.js @@ -0,0 +1,208 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * # `Private()` + * Private module loader, used to merge angular and require js dependency styles + * by allowing a require.js module to export a single provider function that will + * create a value used within an angular application. This provider can declare + * angular dependencies by listing them as arguments, and can be require additional + * Private modules. + * + * ## Define a private module provider: + * ```js + * export default function PingProvider($http) { + * this.ping = function () { + * return $http.head('/health-check'); + * }; + * }; + * ``` + * + * ## Require a private module: + * ```js + * export default function ServerHealthProvider(Private, Promise) { + * let ping = Private(require('ui/ping')); + * return { + * check: Promise.method(function () { + * let attempts = 0; + * return (function attempt() { + * attempts += 1; + * return ping.ping() + * .catch(function (err) { + * if (attempts < 3) return attempt(); + * }) + * }()) + * .then(function () { + * return true; + * }) + * .catch(function () { + * return false; + * }); + * }) + * } + * }; + * ``` + * + * # `Private.stub(provider, newInstance)` + * `Private.stub()` replaces the instance of a module with another value. This is all we have needed until now. + * + * ```js + * beforeEach(inject(function ($injector, Private) { + * Private.stub( + * // since this module just exports a function, we need to change + * // what Private returns in order to modify it's behavior + * require('ui/agg_response/hierarchical/_build_split'), + * sinon.stub().returns(fakeSplit) + * ); + * })); + * ``` + * + * # `Private.swap(oldProvider, newProvider)` + * This new method does an 1-for-1 swap of module providers, unlike `stub()` which replaces a modules instance. + * Pass the module you want to swap out, and the one it should be replaced with, then profit. + * + * Note: even though this example shows `swap()` being called in a config + * function, it can be called from anywhere. It is particularly useful + * in this scenario though. + * + * ```js + * beforeEach(module('kibana', function (PrivateProvider) { + * PrivateProvider.swap( + * function StubbedRedirectProvider($decorate) { + * // $decorate is a function that will instantiate the original module when called + * return sinon.spy($decorate()); + * } + * ); + * })); + * ``` + * + * @param {[type]} prov [description] + */ +import _ from 'lodash'; + +const nextId = _.partial(_.uniqueId, 'privateProvider#'); + +function name(fn) { + return ( + fn.name || + fn + .toString() + .split('\n') + .shift() + ); +} + +export function PrivateProvider() { + const provider = this; + + // one cache/swaps per Provider + const cache = {}; + const swaps = {}; + + // return the uniq id for this function + function identify(fn) { + if (typeof fn !== 'function') { + throw new TypeError('Expected private module "' + fn + '" to be a function'); + } + + if (fn.$$id) return fn.$$id; + else return (fn.$$id = nextId()); + } + + provider.stub = function(fn, instance) { + cache[identify(fn)] = instance; + return instance; + }; + + provider.swap = function(fn, prov) { + const id = identify(fn); + swaps[id] = prov; + }; + + provider.$get = [ + '$injector', + function PrivateFactory($injector) { + // prevent circular deps by tracking where we came from + const privPath = []; + const pathToString = function() { + return privPath.map(name).join(' -> '); + }; + + // call a private provider and return the instance it creates + function instantiate(prov, locals) { + if (~privPath.indexOf(prov)) { + throw new Error( + 'Circular reference to "' + + name(prov) + + '"' + + ' found while resolving private deps: ' + + pathToString() + ); + } + + privPath.push(prov); + + const context = {}; + let instance = $injector.invoke(prov, context, locals); + if (!_.isObject(instance)) instance = context; + + privPath.pop(); + return instance; + } + + // retrieve an instance from cache or create and store on + function get(id, prov, $delegateId, $delegateProv) { + if (cache[id]) return cache[id]; + + let instance; + + if ($delegateId != null && $delegateProv != null) { + instance = instantiate(prov, { + $decorate: _.partial(get, $delegateId, $delegateProv), + }); + } else { + instance = instantiate(prov); + } + + return (cache[id] = instance); + } + + // main api, get the appropriate instance for a provider + function Private(prov) { + let id = identify(prov); + let $delegateId; + let $delegateProv; + + if (swaps[id]) { + $delegateId = id; + $delegateProv = prov; + + prov = swaps[$delegateId]; + id = identify(prov); + } + + return get(id, prov, $delegateId, $delegateProv); + } + + Private.stub = provider.stub; + Private.swap = provider.swap; + + return Private; + }, + ]; +} diff --git a/src/plugins/kibana_legacy/public/utils/register_listen_event_listener.js b/src/plugins/kibana_legacy/public/utils/register_listen_event_listener.js new file mode 100644 index 0000000000000..cce6c98adbbfe --- /dev/null +++ b/src/plugins/kibana_legacy/public/utils/register_listen_event_listener.js @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +export function registerListenEventListener($rootScope) { + /** + * Helper that registers an event listener, and removes that listener when + * the $scope is destroyed. + * + * @param {SimpleEmitter} emitter - the event emitter to listen to + * @param {string} eventName - the event name + * @param {Function} handler - the event handler + * @return {undefined} + */ + $rootScope.constructor.prototype.$listen = function(emitter, eventName, handler) { + emitter.on(eventName, handler); + this.$on('$destroy', function() { + emitter.off(eventName, handler); + }); + }; +} diff --git a/src/legacy/ui/public/system_api/system_api.js b/src/plugins/kibana_legacy/public/utils/system_api.ts similarity index 83% rename from src/legacy/ui/public/system_api/system_api.js rename to src/plugins/kibana_legacy/public/utils/system_api.ts index 8f68c53f8960e..397de4dcc2bb3 100644 --- a/src/legacy/ui/public/system_api/system_api.js +++ b/src/plugins/kibana_legacy/public/utils/system_api.ts @@ -17,6 +17,8 @@ * under the License. */ +import { IRequestConfig } from 'angular'; + const SYSTEM_API_HEADER_NAME = 'kbn-system-api'; /** @@ -24,7 +26,7 @@ const SYSTEM_API_HEADER_NAME = 'kbn-system-api'; * @param originalHeaders Object representing set of headers * @return Object representing set of headers, with system API header added in */ -export function addSystemApiHeader(originalHeaders) { +export function addSystemApiHeader(originalHeaders: Record) { const systemApiHeaders = { [SYSTEM_API_HEADER_NAME]: true, }; @@ -40,6 +42,7 @@ export function addSystemApiHeader(originalHeaders) { * @param request Object Request object created by $http service * @return true if request is a system API request; false otherwise */ -export function isSystemApiRequest(request) { - return !!request.headers[SYSTEM_API_HEADER_NAME]; +export function isSystemApiRequest(request: IRequestConfig) { + const { headers } = request; + return headers && !!headers[SYSTEM_API_HEADER_NAME]; } diff --git a/src/legacy/ui/public/error_url_overflow/url_overflow_service.js b/src/plugins/kibana_legacy/public/utils/url_overflow_service.ts similarity index 87% rename from src/legacy/ui/public/error_url_overflow/url_overflow_service.js rename to src/plugins/kibana_legacy/public/utils/url_overflow_service.ts index bb0df4ee63f92..e0c0f93bf36cd 100644 --- a/src/legacy/ui/public/error_url_overflow/url_overflow_service.js +++ b/src/plugins/kibana_legacy/public/utils/url_overflow_service.ts @@ -22,6 +22,9 @@ const URL_MAX_OTHERS = 25000; export const IE_REGEX = /(; ?MSIE |Edge\/\d|Trident\/[\d+\.]+;.*rv:*11\.\d+)/; export class UrlOverflowService { + private readonly _ieLike: boolean; + private _val?: string | null; + private readonly _sync: () => void; constructor() { const key = 'error/url-overflow/url'; const store = window.sessionStorage || { @@ -37,8 +40,11 @@ export class UrlOverflowService { this._val = store.getItem(key); this._sync = () => { - if (this._val == null) store.removeItem(key); - else store.setItem(key, this._val); + if (typeof this._val === 'string') { + store.setItem(key, this._val); + } else { + store.removeItem(key); + } }; } @@ -46,7 +52,7 @@ export class UrlOverflowService { return this._ieLike ? URL_MAX_IE : URL_MAX_OTHERS; } - set(v) { + set(v: string) { this._val = v; this._sync(); } @@ -55,7 +61,7 @@ export class UrlOverflowService { return this._val; } - check(absUrl) { + check(absUrl: string) { if (!this.get()) { const urlLength = absUrl.length; const remaining = this.failLength() - urlLength; diff --git a/x-pack/legacy/plugins/canvas/public/legacy.ts b/x-pack/legacy/plugins/canvas/public/legacy.ts index 254fba0f23ad2..cbd2aa54627ee 100644 --- a/x-pack/legacy/plugins/canvas/public/legacy.ts +++ b/x-pack/legacy/plugins/canvas/public/legacy.ts @@ -12,7 +12,7 @@ import chrome, { loadingCount } from 'ui/chrome'; // eslint-disable-line import/ import { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; // eslint-disable-line import/order import { Storage } from '../../../../../src/plugins/kibana_utils/public'; // eslint-disable-line import/order // @ts-ignore Untyped Kibana Lib -import { formatMsg } from 'ui/notify/lib/format_msg'; // eslint-disable-line import/order +import { formatMsg } from '../../../../../src/plugins/kibana_legacy/public'; // eslint-disable-line import/order // @ts-ignore Untyped Kibana Lib import { QueryString } from 'ui/utils/query_string'; // eslint-disable-line import/order diff --git a/x-pack/legacy/plugins/graph/public/legacy_imports.ts b/x-pack/legacy/plugins/graph/public/legacy_imports.ts index 702c6cb2d4542..f1839d62a0667 100644 --- a/x-pack/legacy/plugins/graph/public/legacy_imports.ts +++ b/x-pack/legacy/plugins/graph/public/legacy_imports.ts @@ -8,7 +8,6 @@ import 'ui/angular-bootstrap'; import 'ace'; export { SavedObject, SavedObjectKibanaServices } from 'ui/saved_objects/types'; -export { configureAppAngularModule } from 'ui/legacy_compat'; // @ts-ignore export { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; // @ts-ignore @@ -16,3 +15,4 @@ export { confirmModalFactory } from 'ui/modals/confirm_modal'; // @ts-ignore export { addAppRedirectMessageToUrl } from 'ui/notify'; export { createSavedObjectClass } from 'ui/saved_objects/saved_object'; +export { configureAppAngularModule } from '../../../../../src/plugins/kibana_legacy/public'; diff --git a/x-pack/legacy/plugins/monitoring/public/lib/ajax_error_handler.tsx b/x-pack/legacy/plugins/monitoring/public/lib/ajax_error_handler.tsx index 22ce32103c208..c09014b9a9627 100644 --- a/x-pack/legacy/plugins/monitoring/public/lib/ajax_error_handler.tsx +++ b/x-pack/legacy/plugins/monitoring/public/lib/ajax_error_handler.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { contains } from 'lodash'; import { toastNotifications } from 'ui/notify'; // @ts-ignore -import { formatMsg } from 'ui/notify/lib'; +import { formatMsg } from '../../../../../../src/plugins/kibana_legacy/public'; // eslint-disable-line import/order import { EuiButton, EuiSpacer, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 16b96ffe283f0..b558e892895e7 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -181,9 +181,6 @@ "data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage": "保存された {fieldParameter} パラメーターが無効になりました。新しいフィールドを選択してください。", "data.search.aggs.paramTypes.field.requiredFieldParameterErrorMessage": "{fieldParameter} は必須パラメーターです", "data.search.aggs.string.customLabel": "カスタムラベル", - "common.ui.chrome.bigUrlWarningNotificationMessage": "{advancedSettingsLink}で{storeInSessionStorageParam}オプションを有効にするか、オンスクリーンビジュアルを簡素化してください。", - "common.ui.chrome.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高度な設定", - "common.ui.chrome.bigUrlWarningNotificationTitle": "URLが大きく、Kibanaの動作が停止する可能性があります", "common.ui.directives.paginate.size.allDropDownOptionLabel": "すべて", "common.ui.dualRangeControl.mustSetBothErrorMessage": "下と上の値の両方を設定する必要があります", "common.ui.dualRangeControl.outsideOfRangeErrorMessage": "値は {min} と {max} の間でなければなりません", @@ -356,11 +353,6 @@ "common.ui.flotCharts.tueLabel": "火", "common.ui.flotCharts.wedLabel": "水", "common.ui.modals.cancelButtonLabel": "キャンセル", - "common.ui.notify.fatalError.errorStatusMessage": "エラー {errStatus} {errStatusText}: {errMessage}", - "common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP リクエストが接続に失敗しました。Kibana サーバーが実行されていて、ご使用のブラウザの接続が正常に動作していることを確認するか、システム管理者にお問い合わせください。", - "common.ui.notify.toaster.errorMessage": "エラー: {errorMessage}\n {errorStack}", - "common.ui.notify.toaster.errorStatusMessage": "エラー {errStatus} {errStatusText}: {errMessage}", - "common.ui.notify.toaster.unavailableServerErrorMessage": "HTTP リクエストが接続に失敗しました。Kibana サーバーが実行されていて、ご使用のブラウザの接続が正常に動作していることを確認するか、システム管理者にお問い合わせください。", "common.ui.paginateControls.pageSizeLabel": "ページサイズ", "common.ui.paginateControls.scrollTopButtonLabel": "最上部に移動", "common.ui.savedObjects.confirmModal.overwriteButtonLabel": "上書き", @@ -1673,6 +1665,14 @@ "kbn.visualize.wizard.step1Breadcrumb": "作成", "kbn.visualize.wizard.step2Breadcrumb": "作成", "kbn.visualizeTitle": "可視化", + "kibana_legacy.bigUrlWarningNotificationMessage": "{advancedSettingsLink}で{storeInSessionStorageParam}オプションを有効にするか、オンスクリーンビジュアルを簡素化してください。", + "kibana_legacy.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高度な設定", + "kibana_legacy.bigUrlWarningNotificationTitle": "URLが大きく、Kibanaの動作が停止する可能性があります", + "kibana_legacy.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}:{errMessage}", + "kibana_legacy.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。", + "kibana_legacy.notify.toaster.errorMessage": "错误:{errorMessage}\n {errorStack}", + "kibana_legacy.notify.toaster.errorStatusMessage": "错误 {errStatus} {errStatusText}:{errMessage}", + "kibana_legacy.notify.toaster.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。", "home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title": "はじめに", "home.tutorials.common.auditbeat.premInstructions.gettingStarted.title": "はじめに", @@ -13195,4 +13195,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。", "xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 6a352b41235a2..412e31763986c 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -181,9 +181,6 @@ "data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage": "已保存的 {fieldParameter} 参数现在无效。请选择新字段。", "data.search.aggs.paramTypes.field.requiredFieldParameterErrorMessage": "{fieldParameter} 是必需字段", "data.search.aggs.string.customLabel": "定制标签", - "common.ui.chrome.bigUrlWarningNotificationMessage": "在{advancedSettingsLink}中启用“{storeInSessionStorageParam}”选项或简化屏幕视觉效果。", - "common.ui.chrome.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高级设置", - "common.ui.chrome.bigUrlWarningNotificationTitle": "URL 过长,Kibana 可能无法工作", "common.ui.directives.paginate.size.allDropDownOptionLabel": "全部", "common.ui.dualRangeControl.mustSetBothErrorMessage": "下限值和上限值都须设置", "common.ui.dualRangeControl.outsideOfRangeErrorMessage": "值必须是在 {min} 到 {max} 的范围内", @@ -356,11 +353,6 @@ "common.ui.flotCharts.tueLabel": "周二", "common.ui.flotCharts.wedLabel": "周三", "common.ui.modals.cancelButtonLabel": "取消", - "common.ui.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}:{errMessage}", - "common.ui.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。", - "common.ui.notify.toaster.errorMessage": "错误:{errorMessage}\n {errorStack}", - "common.ui.notify.toaster.errorStatusMessage": "错误 {errStatus} {errStatusText}:{errMessage}", - "common.ui.notify.toaster.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。", "common.ui.paginateControls.pageSizeLabel": "页面大小", "common.ui.paginateControls.scrollTopButtonLabel": "滚动至顶部", "common.ui.savedObjects.confirmModal.overwriteButtonLabel": "覆盖", @@ -1673,6 +1665,14 @@ "kbn.visualize.wizard.step1Breadcrumb": "创建", "kbn.visualize.wizard.step2Breadcrumb": "创建", "kbn.visualizeTitle": "可视化", + "kibana_legacy.bigUrlWarningNotificationMessage": "在{advancedSettingsLink}中启用“{storeInSessionStorageParam}”选项或简化屏幕视觉效果。", + "kibana_legacy.bigUrlWarningNotificationMessage.advancedSettingsLinkText": "高级设置", + "kibana_legacy.bigUrlWarningNotificationTitle": "URL 过长,Kibana 可能无法工作", + "kibana_legacy.notify.fatalError.errorStatusMessage": "错误 {errStatus} {errStatusText}:{errMessage}", + "kibana_legacy.notify.fatalError.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。", + "kibana_legacy.notify.toaster.errorMessage": "错误:{errorMessage}\n {errorStack}", + "kibana_legacy.notify.toaster.errorStatusMessage": "错误 {errStatus} {errStatusText}:{errMessage}", + "kibana_legacy.notify.toaster.unavailableServerErrorMessage": "HTTP 请求无法连接。请检查 Kibana 服务器是否正在运行以及您的浏览器是否具有有效的连接,或请联系您的系统管理员。", "home.tutorials.common.auditbeat.cloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.auditbeat.premCloudInstructions.gettingStarted.title": "入门", "home.tutorials.common.auditbeat.premInstructions.gettingStarted.title": "入门", @@ -13194,4 +13194,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} \ No newline at end of file +} From 31985a372563a1a8eeb8900779c1b930f3157684 Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Fri, 7 Feb 2020 11:54:40 +0200 Subject: [PATCH 3/4] TS of esKuery\node_types (#56857) * TS of node types and collector * Code review --- .../node_types/{function.js => function.ts} | 22 ++++++++++++++----- .../kuery/node_types/{index.js => index.ts} | 5 ++++- .../node_types/{literal.js => literal.ts} | 6 +++-- .../node_types/{named_arg.js => named_arg.ts} | 6 +++-- .../kuery/node_types/{index.d.ts => types.ts} | 22 +++++++++---------- .../node_types/{wildcard.js => wildcard.ts} | 22 ++++++++++--------- 6 files changed, 51 insertions(+), 32 deletions(-) rename src/plugins/data/common/es_query/kuery/node_types/{function.js => function.ts} (72%) rename src/plugins/data/common/es_query/kuery/node_types/{index.js => index.ts} (91%) rename src/plugins/data/common/es_query/kuery/node_types/{literal.js => literal.ts} (78%) rename src/plugins/data/common/es_query/kuery/node_types/{named_arg.js => named_arg.ts} (83%) rename src/plugins/data/common/es_query/kuery/node_types/{index.d.ts => types.ts} (81%) rename src/plugins/data/common/es_query/kuery/node_types/{wildcard.js => wildcard.ts} (73%) diff --git a/src/plugins/data/common/es_query/kuery/node_types/function.js b/src/plugins/data/common/es_query/kuery/node_types/function.ts similarity index 72% rename from src/plugins/data/common/es_query/kuery/node_types/function.js rename to src/plugins/data/common/es_query/kuery/node_types/function.ts index c0e7dffde8f5e..5b09bc2a67349 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/function.js +++ b/src/plugins/data/common/es_query/kuery/node_types/function.ts @@ -18,9 +18,13 @@ */ import _ from 'lodash'; +// @ts-ignore import { functions } from '../functions'; +import { IIndexPattern } from '../../..'; +import { FunctionName, FunctionTypeBuildNode } from './types'; +import { JsonValue } from '..'; -export function buildNode(functionName, ...functionArgs) { +export function buildNode(functionName: FunctionName, ...args: any[]) { const kueryFunction = functions[functionName]; if (_.isUndefined(kueryFunction)) { throw new Error(`Unknown function "${functionName}"`); @@ -29,12 +33,15 @@ export function buildNode(functionName, ...functionArgs) { return { type: 'function', function: functionName, - ...kueryFunction.buildNodeParams(...functionArgs), + ...kueryFunction.buildNodeParams(...args), }; } // Mainly only useful in the grammar where we'll already have real argument nodes in hand -export function buildNodeWithArgumentNodes(functionName, argumentNodes) { +export function buildNodeWithArgumentNodes( + functionName: FunctionName, + args: any[] +): FunctionTypeBuildNode { if (_.isUndefined(functions[functionName])) { throw new Error(`Unknown function "${functionName}"`); } @@ -42,11 +49,16 @@ export function buildNodeWithArgumentNodes(functionName, argumentNodes) { return { type: 'function', function: functionName, - arguments: argumentNodes, + arguments: args, }; } -export function toElasticsearchQuery(node, indexPattern, config = {}, context = {}) { +export function toElasticsearchQuery( + node: any, + indexPattern?: IIndexPattern, + config?: Record, + context?: Record +): JsonValue { const kueryFunction = functions[node.function]; return kueryFunction.toElasticsearchQuery(node, indexPattern, config, context); } diff --git a/src/plugins/data/common/es_query/kuery/node_types/index.js b/src/plugins/data/common/es_query/kuery/node_types/index.ts similarity index 91% rename from src/plugins/data/common/es_query/kuery/node_types/index.js rename to src/plugins/data/common/es_query/kuery/node_types/index.ts index 4bca179e2a4d1..6023952b634f2 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/index.js +++ b/src/plugins/data/common/es_query/kuery/node_types/index.ts @@ -21,8 +21,11 @@ import * as functionType from './function'; import * as literal from './literal'; import * as namedArg from './named_arg'; import * as wildcard from './wildcard'; +import { NodeTypes } from './types'; -export const nodeTypes = { +export { NodeTypes }; + +export const nodeTypes: NodeTypes = { function: functionType, literal, namedArg, diff --git a/src/plugins/data/common/es_query/kuery/node_types/literal.js b/src/plugins/data/common/es_query/kuery/node_types/literal.ts similarity index 78% rename from src/plugins/data/common/es_query/kuery/node_types/literal.js rename to src/plugins/data/common/es_query/kuery/node_types/literal.ts index 9fc836660eba3..070ea09e0f647 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/literal.js +++ b/src/plugins/data/common/es_query/kuery/node_types/literal.ts @@ -17,13 +17,15 @@ * under the License. */ -export function buildNode(value) { +import { LiteralTypeBuildNode } from './types'; + +export function buildNode(value: LiteralTypeBuildNode['value']): LiteralTypeBuildNode { return { type: 'literal', value, }; } -export function toElasticsearchQuery(node) { +export function toElasticsearchQuery(node: LiteralTypeBuildNode): LiteralTypeBuildNode['value'] { return node.value; } diff --git a/src/plugins/data/common/es_query/kuery/node_types/named_arg.js b/src/plugins/data/common/es_query/kuery/node_types/named_arg.ts similarity index 83% rename from src/plugins/data/common/es_query/kuery/node_types/named_arg.js rename to src/plugins/data/common/es_query/kuery/node_types/named_arg.ts index d99bc1fcce343..750801990f44e 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/named_arg.js +++ b/src/plugins/data/common/es_query/kuery/node_types/named_arg.ts @@ -20,8 +20,10 @@ import _ from 'lodash'; import * as ast from '../ast'; import { nodeTypes } from '../node_types'; +import { NamedArgTypeBuildNode } from './types'; +import { JsonObject } from '../types'; -export function buildNode(name, value) { +export function buildNode(name: string, value: any): NamedArgTypeBuildNode { const argumentNode = _.get(value, 'type') === 'literal' ? value : nodeTypes.literal.buildNode(value); return { @@ -31,6 +33,6 @@ export function buildNode(name, value) { }; } -export function toElasticsearchQuery(node) { +export function toElasticsearchQuery(node: any): JsonObject { return ast.toElasticsearchQuery(node.value); } diff --git a/src/plugins/data/common/es_query/kuery/node_types/index.d.ts b/src/plugins/data/common/es_query/kuery/node_types/types.ts similarity index 81% rename from src/plugins/data/common/es_query/kuery/node_types/index.d.ts rename to src/plugins/data/common/es_query/kuery/node_types/types.ts index 720d64e11a0f8..1af4a20583d46 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/index.d.ts +++ b/src/plugins/data/common/es_query/kuery/node_types/types.ts @@ -22,9 +22,9 @@ */ import { IIndexPattern } from '../../../index_patterns'; -import { KueryNode, JsonValue } from '..'; +import { JsonValue, KueryNode } from '..'; -type FunctionName = +export type FunctionName = | 'is' | 'and' | 'or' @@ -37,7 +37,7 @@ type FunctionName = interface FunctionType { buildNode: (functionName: FunctionName, ...args: any[]) => FunctionTypeBuildNode; - buildNodeWithArgumentNodes: (functionName: FunctionName, ...args: any[]) => FunctionTypeBuildNode; + buildNodeWithArgumentNodes: (functionName: FunctionName, args: any[]) => FunctionTypeBuildNode; toElasticsearchQuery: ( node: any, indexPattern?: IIndexPattern, @@ -46,7 +46,7 @@ interface FunctionType { ) => JsonValue; } -interface FunctionTypeBuildNode { +export interface FunctionTypeBuildNode { type: 'function'; function: FunctionName; // TODO -> Need to define a better type for DSL query @@ -58,40 +58,38 @@ interface LiteralType { toElasticsearchQuery: (node: any) => null | boolean | number | string; } -interface LiteralTypeBuildNode { +export interface LiteralTypeBuildNode { type: 'literal'; value: null | boolean | number | string; } interface NamedArgType { buildNode: (name: string, value: any) => NamedArgTypeBuildNode; - toElasticsearchQuery: (node: any) => string; + toElasticsearchQuery: (node: any) => JsonValue; } -interface NamedArgTypeBuildNode { +export interface NamedArgTypeBuildNode { type: 'namedArg'; name: string; value: any; } interface WildcardType { - buildNode: (value: string) => WildcardTypeBuildNode; + buildNode: (value: string) => WildcardTypeBuildNode | KueryNode; test: (node: any, string: string) => boolean; toElasticsearchQuery: (node: any) => string; toQueryStringQuery: (node: any) => string; hasLeadingWildcard: (node: any) => boolean; } -interface WildcardTypeBuildNode { +export interface WildcardTypeBuildNode { type: 'wildcard'; value: string; } -interface NodeTypes { +export interface NodeTypes { function: FunctionType; literal: LiteralType; namedArg: NamedArgType; wildcard: WildcardType; } - -export const nodeTypes: NodeTypes; diff --git a/src/plugins/data/common/es_query/kuery/node_types/wildcard.js b/src/plugins/data/common/es_query/kuery/node_types/wildcard.ts similarity index 73% rename from src/plugins/data/common/es_query/kuery/node_types/wildcard.js rename to src/plugins/data/common/es_query/kuery/node_types/wildcard.ts index 8c6bf1009b3a1..87fcfa1ca2f64 100644 --- a/src/plugins/data/common/es_query/kuery/node_types/wildcard.js +++ b/src/plugins/data/common/es_query/kuery/node_types/wildcard.ts @@ -18,20 +18,22 @@ */ import { fromLiteralExpression } from '../ast/ast'; +import { WildcardTypeBuildNode } from './types'; +import { KueryNode } from '..'; export const wildcardSymbol = '@kuery-wildcard@'; // Copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions -function escapeRegExp(string) { - return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +function escapeRegExp(str: string) { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string } // See https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#_reserved_characters -function escapeQueryString(string) { - return string.replace(/[+-=&|> Date: Fri, 7 Feb 2020 11:19:15 +0100 Subject: [PATCH 4/4] fix auto closing new vis modal when navigating to lens or when navigating away with browser history (#56998) Co-authored-by: Elastic Machine --- .../np_ready/listing/visualize_listing.js | 12 ++++++++--- .../public/wizard/new_vis_modal.test.tsx | 20 +++++++++++++++++++ .../np_ready/public/wizard/new_vis_modal.tsx | 2 +- .../np_ready/public/wizard/show_new_vis.tsx | 5 +++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js index 6bac4e4c62efa..cae1e40cd445a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/listing/visualize_listing.js @@ -32,7 +32,7 @@ export function initListingDirective(app) { ); } -export function VisualizeListingController($injector, createNewVis) { +export function VisualizeListingController($injector, $scope, createNewVis) { const { addBasePath, chrome, @@ -59,7 +59,7 @@ export function VisualizeListingController($injector, createNewVis) { this.savedObjects = savedObjects; this.createNewVis = () => { - visualizations.showNewVisModal(); + this.closeNewVisModal = visualizations.showNewVisModal(); }; this.editItem = ({ editUrl }) => { @@ -73,7 +73,7 @@ export function VisualizeListingController($injector, createNewVis) { if (createNewVis) { // In case the user navigated to the page via the /visualize/new URL we start the dialog immediately - visualizations.showNewVisModal({ + this.closeNewVisModal = visualizations.showNewVisModal({ onClose: () => { // In case the user came via a URL to this page, change the URL to the regular landing page URL after closing the modal kbnUrl.changePath(VisualizeConstants.LANDING_PAGE_PATH); @@ -124,4 +124,10 @@ export function VisualizeListingController($injector, createNewVis) { this.listingLimit = uiSettings.get('savedObjects:listingLimit'); addHelpMenuToAppChrome(chrome, docLinks); + + $scope.$on('$destroy', () => { + if (this.closeNewVisModal) { + this.closeNewVisModal(); + } + }); } diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.test.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.test.tsx index 0701b5042a4bd..58f7bc49d1cdb 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.test.tsx +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.test.tsx @@ -155,6 +155,26 @@ describe('NewVisModal', () => { expect(window.location.assign).toBeCalledWith('testbasepath/aliasUrl?addToDashboard'); expect(onClose).toHaveBeenCalled(); }); + + it('closes and redirects properly if visualization with aliasUrl and without addToDashboard in editorParams', () => { + const onClose = jest.fn(); + window.location.assign = jest.fn(); + const wrapper = mountWithIntl( + + ); + const visButton = wrapper.find('button[data-test-subj="visType-visWithAliasUrl"]'); + visButton.simulate('click'); + expect(window.location.assign).toBeCalledWith('testbasepath/aliasUrl'); + expect(onClose).toHaveBeenCalled(); + }); }); describe('filter for visualization types', () => { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.tsx index fe66d2e56c611..b39e8e8926707 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.tsx +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/wizard/new_vis_modal.tsx @@ -145,8 +145,8 @@ class NewVisModal extends React.Component { + if (isClosed) return; ReactDOM.unmountComponentAtNode(container); document.body.removeChild(container); if (onClose) { onClose(); } + isClosed = true; }; document.body.appendChild(container); @@ -55,4 +58,6 @@ export function showNewVisModal({ editorParams = [], onClose }: ShowNewVisModalP ); ReactDOM.render(element, container); + + return () => handleClose(); }